Waiting for Invoke to finish when using IOmniTaskControl/TOmniWorker

不问归期 提交于 2019-12-07 14:35:55

问题


I've created an IOmniTaskControl using a TOmniWorker, so that I can periodically run chunks of code an a specific thread. So I'll be calling Invoke as needed on this IOmniTaskControl. When I do so, I will sometimes need to wait for the execution associated with that work to complete.

I tried calling WaitFor(INFINITE) on the IOmniTaskControl after the Invoke, but it hangs. I debugged and could see the method on the Invoke call completed. Am I misunderstanding the use of WaitFor with IOmniTaskControl when used with a TOmniWorker?

Edit: I edited up the test_43_InvokeAnonymous project in the test folder and I see the same behavior:

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;

With the above code, the task.WaitFor(INFINITE); hangs.


回答1:


WaitFor waits for the task to finish execution but as nobody told the task to terminate, it will wait forever.

Scheduling a background operation and then waiting for it more or less defeats the purpose of a background execution. It is better to schedule a background task and then send a notification back to the main thread when the task is finished. Use any variation of OnMessage (in the main thread) and Task.Comm.Send (in the worker).

Even better way would be to use Parallel.Future, which encapsulates exactly what you want to do.

If you really have to wait on the Invoke to complete, you can create a waitable value before the Invoke, signal it in the code executed by the Invoke and wait for it in the code that called the Invoke.



来源:https://stackoverflow.com/questions/36047891/waiting-for-invoke-to-finish-when-using-iomnitaskcontrol-tomniworker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!