你真的应该使用工作线程。这就是线程的好处。
使用Application.ProcessMessages()
是创可贴,而不是解决方案。您的应用程序在工作时仍将无响应DoTask()
,除非您乱扔垃圾DoTask()
对Application.ProcessMessages()
. Application.ProcessMessages()
另外,如果您不小心,直接调用会引入可重入问题。
如果您必须Application.ProcessMessages()
直接调用,那么除非有消息实际等待处理,否则不要调用它。您可以使用 Win32 APIGetQueueStatus()
函数来检测这种情况,例如:
// time-consuming loop
For I := 0 to 1024 * 65536 do
Begin
DoTask();
if GetQueueStatus(QS_ALLINPUT) <> 0 then
Application.ProcessMessages;
End;
否则,将DoTask()
循环移动到一个线程中(是的,是的),然后让你的主循环用于MsgWaitForMultipleObjects()
等待任务线程完成。这仍然允许您检测何时处理消息,例如:
procedure TMyTaskThread.Execute;
begin
// time-consuming loop
for I := 0 to 1024 * 65536 do
begin
if Terminated then Exit;
DoTask();
end;
end;
var
MyThread: TMyTaskThread;
Ret: DWORD;
begin
...
MyThread := TMyTaskThread.Create;
repeat
Ret := MsgWaitForMultipleObjects(1, Thread.Handle, FALSE, INFINITE, QS_ALLINPUT);
if (Ret = WAIT_OBJECT_0) or (Ret = WAIT_FAILED) then Break;
if Ret = (WAIT_OBJECT_0+1) then Application.ProcessMessages;
until False;
MyThread.Terminate;
MyThread.WaitFor;
MyThread.Free;
...
end;