MarkShark 27 Posted July 27, 2021 (edited) Summary: Using a Parallel.BackgroundWorker if I check for WorkItem.CancellationToken.IsSignalled within the .OnExecute anonymous procedure I see that it is terminated immediately if I call FWorker.CancelAll from the main thread. HOWEVER if I use a function called from the OnExecute handler it seems that the token is only signaled once the function completes. I've included some code below, but if anyone could explain what I'm seeing it would be much appreciated! Using a Paralel.BackgroundWorker created like: FWorker := Parallel.BackgroundWorker.Execute(nil); I then schedule a work item like: FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.Null), FWorker.Config .OnExecute( procedure(const WorkItem: IOmniWorkItem) begin var LElapsed: Integer := 1; repeat Sleep(100); Inc(LElapsed, 100); until WorkItem.CancellationToken.IsSignalled or (LElapsed > 5000); end) .OnRequestDone( procedure (const Sender: IOmniBackgroundWorker; const WorkItem: IOmniWorkItem) begin if WorkItem.CancellationToken.IsSignalled then Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone and was cancelled.') else Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone'); end ) ); Calling FWorker.CancelAll; from the main thread cancels this workitem immediately. However if instead of the "repeat until" above I call the following function, the token is never signaled "during the call", though it is signaled after the call returns. function NiceWaitEx(const ACancelToken: IOmniCancellationToken; AWaitMs: Integer): Integer; begin const LagMs = 100; var LElapsed: Integer := 1; repeat Sleep(LagMs); Inc(LElapsed, LagMs); until ACancelToken.IsSignalled or (LElapsed > AWaitMs); Result := LElapsed; end; FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.Null), FWorker.Config .OnExecute( procedure(const WorkItem: IOmniWorkItem) begin NiceWaitEx(WorkItem.CancellationToken, 5000); end) .OnRequestDone( procedure (const Sender: IOmniBackgroundWorker; const WorkItem: IOmniWorkItem) begin if WorkItem.CancellationToken.IsSignalled then Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone and was cancelled.') else Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone'); end ) ); When I use the second version (with the call) the workitem always goes the full 5 seconds although shows that it was cancelled at the end. I hope that's enough to explain the issue (and my confusion lol.) Any thoughts appreciated! -Mark Edited July 27, 2021 by MarkShark clarifying Share this post Link to post