Hi Folks
Hi Folks,
I'm trying to find out, how a long running task created with TTask.Run() can be terminated properly upon program termination.
I tried to build upon the example at https://stackoverflow.com/questions/44080089/how-to-stop-a-running-ttask-thread-safe.
I have no problem starting, stopping tasks from the GUI. Stopping an unfinished task and starting the next also works, but the application reliably crashes when I start a task and exit the application immediately.
In the destructor of the example project the result list is just freed. This will of course cause an A/V, because the still running task is trying to add entries to the list. Calling Task.Cancel in the destructor before freeing the list doesn't help ;)
I need a reliable way to cancel a running task and wait for its termination in e.g. FormClose(). My attempts have failed so far.
I can make my test application available via dropbox/google drive.
https://stackoverflow.com/questions/44080089/how-to-stop-a-running-ttask-thread-safe
I'm trying to find out, how a long running task created with TTask.Run() can be terminated properly upon program termination.
I tried to build upon the example at https://stackoverflow.com/questions/44080089/how-to-stop-a-running-ttask-thread-safe.
I have no problem starting, stopping tasks from the GUI. Stopping an unfinished task and starting the next also works, but the application reliably crashes when I start a task and exit the application immediately.
In the destructor of the example project the result list is just freed. This will of course cause an A/V, because the still running task is trying to add entries to the list. Calling Task.Cancel in the destructor before freeing the list doesn't help ;)
I need a reliable way to cancel a running task and wait for its termination in e.g. FormClose(). My attempts have failed so far.
I can make my test application available via dropbox/google drive.
https://stackoverflow.com/questions/44080089/how-to-stop-a-running-ttask-thread-safe
Have you tried terminating your threads from a handler of OnCloseQuery instead of OnClose?
ReplyDelete/sub
ReplyDeletequality.embarcadero.com - Log in - Embarcadero Technologies
ReplyDeletethe commonly used pattern
Cancel;
try
Wait;
except
end;
used in TTask.Destroy does not work! One has to wrap Wait in a separate task.
t2 = TTask.Run(procedure
begin
try
t1.Wait;
except
end;
end);
t1.Cancel;
t2.Wait;
I would suggest that you use some other way to signal to your long running task to stop. e.g.
StopRunning := True.
Task.Wait;
or you can patch your System.Threading as suggested in the report.
Kiriakos Vlahos Very interesting. Looks like you're fighting the same problems that I do. I tried to wrap the cancel/wait in a separate task as you suggested, but my test application still crashes.
ReplyDeleteIn the SO example it would be the following line inside the parallel for loop:
if (Task.Status=TTaskStatus.Canceled) and not(LoopState.Stopped) then
In the debugger it looks like Task has already gone out of scope while the for loop is still running.
Lübbe Onken Do you cancel the task and wait for a completed notification before closing the form? I'm afraid that is the only sensible solution. Use the OnCloseQuery to notify the user if the task is not stopped yet.
ReplyDeleteSee at stackoverflow a version that works without ITask.Cancel.
ReplyDeleteIf your long running task calls TThread.Synchronize waiting for that task in the main thread blocks. You can use TThread.Queue instead or else something like:
ReplyDeletewhile Task.Status <> Completed do
Application.ProcessMessages;
Leif Uneus basically it’s an async/await pattern. But it doesn’t reach the await part and I don’t get the notification.
ReplyDeleteMy next try will be an arrray of itask + waitforall instead of parallel for. If that doesn‘t work, I’ll try a different signaling instead of task.cancel.
Kiriakos Vlahos I’ll check that tomorrow, thank you.
ReplyDeleteBoy, this is tough. I have a notify callback (which I think I need) and this is causing trouble when the application is terminated while there is still a running task. I added my current state to Kiriakos Vlahos solution on SO. Hopefully someone can shed some insight what I'm doing wrong. Otherwise I'll try to find a way without the notify callback.
ReplyDeleteForget about System.Threading and just use the OTL ;) Primož Gabrijelčič fyi :)
ReplyDeleteStefan Glienke for some reason I was expecting this answer already yesterday ;)
ReplyDeleteSee comment at Stackoverflow
ReplyDeleteKiriakos Vlahos Thanks! CheckSynchronize during Shutdown did the trick. This also allowed me to get rid of the additional flag. Thanks to your help I'd say that we now have a good and working solution for the problem.
ReplyDeleteStefan Glienke Except for the Cancel mess, I found the PPL to be elegant and efficient, based on modern locking mechanisms. Just don't use Cancel until it gets fixed. Marco Cantù Please fix this because it deters usage of a great library.
ReplyDelete