Lar*_*qua 3 delphi omnithreadlibrary delphi-xe5
我已经使用TOmniWorker创建了IOmniTaskControl,以便可以在特定线程中定期运行代码块。因此,我将根据需要在此IOmniTaskControl上调用Invoke。当我这样做时,有时需要等待与该工作相关的执行完成。
我尝试在调用之后在IOmniTaskControl上调用WaitFor(INFINITE),但是它挂起了。我进行了调试,可以看到Invoke调用上的方法已完成。与TOmniWorker一起使用时,我是否误将WaitFor与IOmniTaskControl一起使用?
编辑:我在测试文件夹中编辑了test_43_InvokeAnonymous项目,并且看到了相同的行为:
procedure TfrmInvokeAnonymousDemo.btnInvokeClick(Sender: TObject);
var
formThreadID: DWORD;
task : IOmniTaskControl;
begin
formThreadID := GetCurrentThreadID;
if Sender = btnInvoke then
task := FTask
else
task := FMonitoredTask;
task.Invoke(
procedure (const task: IOmniTask)
var
taskThreadID: DWORD;
begin
// this will execute in the context of the worker thread
taskThreadID := GetCurrentThreadID;
Sleep(2000);
// task.Invoke(
// procedure
// begin
// // this will execute in the context of the main thread
// frmInvokeAnonymousDemo.lbLog.Items.Add(Format(
// 'Current thread ID: %d, task thread ID: %d, ' +
// ' form thread ID: %d',
// [GetCurrentThreadID, taskThreadID, formThreadID]));
// end
// );
end
);
task.WaitFor(INFINITE);
frmInvokeAnonymousDemo.lbLog.Items.Add('Done waiting.');
end;
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,task.WaitFor(INFINITE);挂起。
WaitFor 等待任务完成执行,但是由于没有人告诉任务终止,它将永远等待。
安排后台操作,然后或多或少地等待它会破坏后台执行的目的。最好安排一个后台任务,然后在任务完成时将通知发送回主线程。使用OnMessage(在主线程中)和Task.Comm.Send(在工作线程中)的任何变体。
甚至更好的方法是使用Parallel.Future,它完全封装了您想要执行的操作。
如果您确实需要等待Invoke完成,则可以在之前创建一个可等待的值Invoke,在由其执行的代码中用信号通知并在称为的代码中Invoke等待它Invoke。