这是等待Thread.finalization并保持我的应用程序响应的正确方法

时间:2010-11-16 03:07:56

标签: multithreading delphi waitforsingleobject

其实我正在使用这段代码并且工作正常,但我想知道是否是正确的方法。

  while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
    Application.ProcessMessages;

  ShowMessage('i am done');

5 个答案:

答案 0 :(得分:13)

VCL TThread类有自己的WaitFor()方法,在主线程上下文中调用时会在内部泵送主消息队列:

MyThread.WaitFor; 
ShowMessage('i am done'); 

答案 1 :(得分:8)

调用Application.ProcessMessages通常被视为代码气味。如果它没有任何关系,让你的主线程空闲。

如果你经营一家公司并需要你的一名工人跑到商店去买一些急需的用品,你会不会在门口走,直到他回来,或者你更愿意坐在你的办公室休息并等待他,并发现供应品在这里,因为你听到他走进门口?无论哪种方式,他都会花费相同的时间,但第一种方式就是把你的腿伸出来。

同样,不要让您的UI观看线程,而是让线程报告回UI。一种方法是让线程使用PostMessage将自定义消息发送到完成后启动它的表单,并在表单上放置一个消息处理程序来响应它。

答案 2 :(得分:2)

看起来是正确的(如果正确则意味着它可以完成工作)。我要改变的是等待更多时间(50ms看起来很好,以保持应用程序响应)而不吃CPU。

while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
  Application.ProcessMessages;
ShowMessage('i am done');

当然还有其他方法可以做到这一点......<笑话>但我通常会采用以下主要工程原则之一:

如果有效,请勿触摸!< / joke>

答案 3 :(得分:2)

我同意Mason Wheeler的评论,主线程最好留下来完成它的工作,但我建议在线程上使用OnTerminate事件。它更像是“Delphi自然”,而内部逻辑为您提供了PostMessage位。由于TThread不是组件,因此您无法在对象检查器中查看它,并且必须自己编写和附加事件处理程序。它在线程完成/终止后被调用(在主线程中!)。

答案 4 :(得分:1)

虽然它看起来没问题,但jachguate我也会使用比0更大的超时值。如果使用WaitForSingleObject(MyThread.Handle, 100),主线程将等待一段时间,从而占用更少的CPU周期 但是,更好的解决方案是使用消息。您的应用程序启动该线程,然后将所有控件置于禁用模式。然后线程执行,当它完成时,使用SendMessagePostMessage到主窗口通知它线程再次完成。然后您的应用程序将再次启用每个控件(以及其他任何控件)。这样做有利于保持应用程序的“自然”消息循环,而不是使用此解决方案运行自己的messageloop。
不幸的是,消息方法有一个缺点:如果线程崩溃,那么将不会有任何消息寄回,所以备份计划是实用的。例如,通过向mainform添加一个计时器控件,如果线程仍处于活动状态,则每秒检查一次。如果没有,它也会再次激活表单,再次禁用它。