以便携的方式运行应用并忘记它

3
我正在编写一个小型更新程序,该程序从主程序中调用。主程序在调用后立即终止,让更新程序复制所有更新文件,然后应该重新启动主程序。然而,最后这一部分开始让我头疼。
我可以使用std::system运行程序(我知道不安全,但是可移植),但更新程序会卡在那里等待主程序完成。我正在寻找使呼叫“fire & forget”并使线程像最佳方法的方式。
然而,下面的代码:
std::system("app");

挂起更新程序,因为它在等待system的返回。与此不同的是:
std::thread(std::system, "app").detach();

不变式
std::thread t(std::system, "app");
t.detach();

看起来没有做任何事情。但是当我使用以下代码加入线程时:

std::thread t(std::system, "app");
t.join();

它确实可以运行应用程序,但仍像原始代码一样等待其返回。为什么分离的线程无法运行该应用程序?


1
你需要哪个级别的可移植性(即哪些平台是感兴趣的)? - Jason R
@JasonR 主要的应用程序是一个Qt应用程序,我针对3个Qt平台进行开发:桌面、Linux和Mac... - Resurrection
1
QProcess 不合适吗? - Nicolas Holthaus
很不幸,是的。我不能使用静态构建的Qt,因此任何基于Qt的更新程序都需要依赖于Qt。因此,我需要关闭使用QProcess调用更新程序的Qt应用程序,并使用非Qt外部更新程序来完成工作并重新启动Qt应用程序,或者维护两个Qt部署(一个用于应用程序,一个用于更新程序),并在更新任一部分时同时更新两个部分。我认为外部的非Qt应用程序会是更好的解决方案。 - Resurrection
2个回答

2

无论线程是否被分离,如果其所属进程结束(在大部分系统上),线程都将会死亡。在更新程序结束执行之前给一些时间,线程可能能够实际进行调用:

#include <chrono>
#include <cstdlib>
#include <thread>

void do_app() {
  std::system("app");
}

int main() {
  std::thread(do_app).detach();
  std::this_thread::sleep_for(std::chrono::seconds(2));
} 

太棒了。:-) 它确实起作用了... 我没有想到这会是个问题,因为我读到了关于“主函数返回后会发生什么”的混乱信息,有些人声称它会被杀死(显然是这样),而有些人则不是。 - Resurrection
这是因为标准实际上并没有定义当主程序执行结束时,会发生什么事情。每个系统都可能做任何事情。某些奇特的系统可能会保持线程继续执行,但大多数系统不会这样做。 - Cássio Renan

1
我会在不同的实现周围使用ifdef块。对于Windows,您可以使用CreateProcess,linux(以及可能的Mac)支持POSIX popen / fork方法。
std :: system实际上并不能使您的程序具有可移植性,因为通常在各个平台上调用shell的语法略有不同,您最终还是会得到平台相关的代码。
这里有一个关于如何在Linux中执行的详细教程: http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html 而对于Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

谢谢,我会研究一下。在更新程序被调用时,通过将实际的命令从主程序传递给调用方法,可以解决不同的调用方法。 - Resurrection

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接