你真的应该使用工作线程。这就是线程的好处。
使用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;