我如何保证我的win32应用程序快速关机?

时间:2008-10-16 15:35:38

标签: c++ multithreading winapi exit

我有一个C ++ Win32应用程序,当用户想要关闭应用程序时,它有许多线程可能正忙于执行IO(HTTP调用等)。目前,我很好地玩,等待所有线程结束,然后从main返回。有时,这比我想要的时间更长,事实上,当我可以退出时让用户等待似乎毫无意义。但是,如果我继续从main返回,我可能会遇到崩溃,因为析构函数开始被调用,而仍有线程使用这些对象。

因此,认识到在一个理想的,柏拉图式的美德世界中,最好的办法是等待所有线程退出然后干净地关闭,下一个最好的真实解决方案是什么?简单地让线程退出更快可能不是一种选择。目标是尽可能快地使进程失效,例如,可以在其上安装新版本。我正在做的唯一磁盘IO是在事务数据库中,所以我并不十分担心拔掉插件。

11 个答案:

答案 0 :(得分:7)

使用重叠IO,这样您就可以随时控制处理I / O的线程,并且可以随时停止它们;你要么让他们等待IOCP并向他们发布一个应用程序级别的关闭代码,要么你可以等待OVERLAPPED结构中的事件并等待你的“所有线程请立即关闭”事件。

总之,请避免阻止您无法取消的通话。

如果你不能和你陷入阻塞套接字调用做IO那么你总是可以从线程中关闭套接字,该线程决定是时候关闭并让正在做IO的线程总是检查在重试之前'立即关闭'事件......

答案 1 :(得分:5)

我使用基于异常的技术,在许多Win32应用程序中对我来说非常好用。

要终止一个线程,我使用QueueUserAPC()将一个调用队列排入一个抛出异常的函数。但是,抛出的异常不是从“Exception”类型派生的,因此只能由我的线程的包装程序捕获。

这样做的好处如下:

  • 您的线程中不需要特殊代码使其“可停止” - 只要它进入可警告的等待状态,它就会运行APC功能。
  • 当异常在堆栈中运行时,所有析构函数都会被调用,因此您的线程会完全退出。

您需要注意的事项:

  • 任何正在做catch (...)的事都会吃掉你的例外。用户代码应始终使用catch(const Exception &e)或类似名称!
  • 确保您的I / O和延迟以“警报”方式完成。例如,这意味着调用sleepex(N, true)而不是sleep(N)
  • CPU绑定线程需要偶尔调用sleepex(0,true)来检查终止。

您还可以“保护”代码区域,以防止在关键部分中终止任务。

答案 2 :(得分:2)

最佳方式:在应用程序运行时执行您的工作,并在关机时不执行任何操作(或接近启动)(也适用于启动)。如果您坚持使用该模式,那么当关闭请求到来时,您可以立即拆除线程(而不是“很好”),而不必担心仍需要完成的工作。

在您的具体情况下,如果您在那里做本地工作,您可能需要等待IO完成(至少写入)。 HTTP请求,你可以直接放弃/关闭(再次,除非你写的东西)。但是,如果您在此关闭期间正在编写并等待它,那么您可能希望通知用户,而不是让您的流程在您收尾时让您的流程处于挂起状态。

答案 3 :(得分:2)

我建议让你的GUI和工作在不同的线程上完成。当用户请求关闭时,立即关闭GUI,使应用程序已关闭。允许工作线程在后台正常关闭。

答案 4 :(得分:0)

如果你想搞乱插头,退出(0)就可以了。

答案 5 :(得分:0)

我曾经遇到类似的问题,尽管在Visual Basic 6中:来自应用程序的线程将连接到不同的服务器,下载一些数据,执行一些循环访问该数据的操作,并将结果存储在中央服务器上。

然后,新要求是线程应该从主窗体中停止。我以简单但脏的方式实现了这一点,通过在N次循环(大约相当于半秒)后线程停止尝试打开具有特定名称的互斥锁。一旦成功,他们立即停止了他们正在做的事情并退出,否则继续。

这个互斥锁只是由主窗体创建的,一旦创建它,​​所有线程很快就会关闭。缺点是用户需要手动指定它想要再次运行线程 - 另一个“启用线程运行”的按钮通过释放互斥锁完成此操作:D

这个技巧保证适用于互斥操作是原子的。问题是你永远不会确定一个线程真正关闭 - 处理“openMutex成功”案例的逻辑失败可能意味着它永远不会结束。您还不知道所有线程何时/是否已关闭(假设您的代码是正确的,这将花费大致相同的时间来停止循环并“监听”)。

使用VB的“公寓”多线程模型,从线程向主要应用程序来回发送信息有点困难,更容易“发射并忘记”或仅将其从主应用程序发送到线。因此,需要这种长切。使用C ++,您可以自由使用多线程模型,因此这些约束可能不适用于您。

答案 6 :(得分:0)

无论你做什么, NOT 使用TerminateThread,尤其是在OS HTTP调用中可能出现的任何事情。您可能会破坏IE直到重新启动。

将所有IO更改为异步或非阻塞模型,以便他们可以监视终止事件。

答案 7 :(得分:0)

如果你需要突然关机:只需调用ExitProcess - 无论如何,只要你从WinMain返回就会调用它。 Windows本身会创建许多无法清理的工作线程 - 它们会被进程关闭终止。

如果您有任何执行某种写入的线程 - 显然那些需要有机会关闭其资源。但其他任何事情 - 忽略边界检查警告,只是从他们脚下拉地毯。

答案 8 :(得分:0)

您可以调用TerminateProcess - 这将立即停止该过程,而无需通知任何人,也无需等待任何事情。

答案 9 :(得分:0)

*NULL = 0是最快的方法。如果您不想崩溃,请拨打exit()或其等效的win32。

答案 10 :(得分:-5)

指示用户拔下电脑插头。除此之外,您必须放弃异步活动。还是HWIND?我永远不会记得在C ++中。当然,您可以走中间道路并快速记录文本文件或reg键,放弃了哪些操作,以便下次程序运行时可以自动再次执行该操作,或者询问用户是否要这样做。根据您放弃异步操作时丢失的数据,您可能无法执行此操作。如果您正在与用户进行交互,您可能需要考虑一个对话框或一些UI交互,以解释为什么它花了这么长时间。

就个人而言,我更喜欢用户只需拔掉电脑的指令。 :)