实际上我正在使用这段代码并且工作正常,但我想知道是否是正确的方法。
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
实际上我正在使用这段代码并且工作正常,但我想知道是否是正确的方法。
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
VCL TThread 类有它自己的WaitFor()
方法,当在主线程上下文中调用时,它会在内部抽取主消息队列:
MyThread.WaitFor;
ShowMessage('i am done');
调用Application.ProcessMessages
通常被认为是代码异味。如果它无事可做,让你的主线程空闲。
如果你经营一家公司,需要你的一名工人跑到商店去拿一些急需的物资,你会在门口踱步直到他回来,还是更愿意坐在办公室里休息等待他,发现补给品在这里是因为你听到他进门了吗?无论哪种方式,他都会花费相同的时间,但第一种方式会让你的腿筋疲力尽。
同样,不要让你的 UI 监视线程,而是让线程向 UI 报告。一种方法是让线程PostMessage
在完成后将自定义消息发送到启动它的表单,并在表单上放置一个消息处理程序以响应它。
它看起来是正确的(如果正确意味着它可以完成工作)。我要改变的是在不占用 CPU 的情况下等待更多时间(50ms 看起来不错以保持应用程序响应)。
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
当然还有其他方法可以做到这一点...... <笑话>但我通常会应用主要的工程原则之一:
如果它有效,请不要触摸它!</笑话>
我同意 Mason Wheeler 的说法,最好让主线程来完成它的工作,但我建议在线程上使用 OnTerminate 事件。它更“自然德尔福”,内部逻辑为您完成 PostMessage 位。由于 TThread 不是组件,因此您无法在对象检查器中查看它,并且必须自己编写和附加事件处理程序。它在线程完成/终止后被调用(在主线程中!)。
虽然看起来不错,但像jachguate我也会使用比 0 更大的超时值。如果您使用WaitForSingleObject(MyThread.Handle, 100)
,则主线程将等待更长的时间,从而消耗更少的 CPU 周期。
不过,更好的解决方案是使用消息。您的应用程序启动线程,然后将所有控件置于禁用模式。然后线程执行,当它完成时,使用SendMessage或PostMessage到主窗口来通知它线程再次完成。然后您的应用程序将再次启用每个控件(以及其他任何控件)。这样做的好处是您可以保持应用程序的“自然”消息循环处于活动状态,而不是使用此解决方案运行您自己的消息循环。
不幸的是,消息方法有一个缺点:如果线程崩溃,则不会发回任何消息,因此备份计划是可行的。例如,通过向主窗体添加一个计时器控件,该控件每秒检查线程是否仍处于活动状态。如果没有,它也只会再次激活表单,再次禁用自身。