使用IOmniTaskControl / TOmniWorker时等待Invoke完成

时间:2016-03-16 22:08:47

标签: delphi delphi-xe5 omnithreadlibrary

我使用TOmniWorker创建了一个IOmniTaskControl,这样我就可以定期运行特定线程的代码块。所以我将根据需要在此IOmniTaskControl上调用Invoke。当我这样做时,我有时需要等待与该工作相关的执行完成。

我在Invoke之后尝试在IOmniTaskControl上调用WaitFor(INFINITE),但它挂起了。我调试了,可以看到完成Invoke调用的方法。与TOmniWorker一起使用时,我是否误解了WaitFor与IOmniTaskControl的使用?

编辑:我在test文件夹中编辑了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;

使用上面的代码,task.WaitFor(INFINITE);会挂起。

1 个答案:

答案 0 :(得分:4)

WaitFor等待任务完成执行但由于没有人告诉任务终止,它将永远等待。

调度后台操作然后或多或少地等待它会破坏后台执行的目的。最好安排后台任务,然后在任务完成时将通知发送回主线程。使用OnMessage(在主线程中)和Task.Comm.Send(在工作者中)的任何变体。

更好的方法是使用Parallel.Future,它完全封装了您想要做的事情。

如果您真的需要等待Invoke完成,可以在Invoke之前创建waitable value,并在Invoke执行的代码中发出信号,在调用Invoke

的代码中等待它