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

Comments

  1. Have you tried terminating your threads from a handler of OnCloseQuery instead of OnClose?

    ReplyDelete
  2. quality.embarcadero.com - Log in - Embarcadero Technologies

    the 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.

    ReplyDelete
  3. 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.
    In 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.

    ReplyDelete
  4. 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.

    ReplyDelete
  5. See at stackoverflow a version that works without ITask.Cancel.

    ReplyDelete
  6. If 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:
    while Task.Status <> Completed do
    Application.ProcessMessages;

    ReplyDelete
  7. Leif Uneus basically it’s an async/await pattern. But it doesn’t reach the await part and I don’t get the notification.
    My 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.

    ReplyDelete
  8. Kiriakos Vlahos I’ll check that tomorrow, thank you.

    ReplyDelete
  9. Boy, 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.

    ReplyDelete
  10. Forget about System.Threading and just use the OTL ;) Primož Gabrijelčič fyi :)

    ReplyDelete
  11. Stefan Glienke for some reason I was expecting this answer already yesterday ;)

    ReplyDelete
  12. Kiriakos 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.

    ReplyDelete
  13. Stefan 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

Post a Comment