Search code examples
c#wpfmultithreadingmvvmasync-await

How to avoid threaded Task to be Garbage Collected?


Suppose you want to execute a static Task without awaiting it, and you want to execute this Task in a Command of a ViewModel instance of a page, in a MVVM project.

This Task should just call an API to send some event info, and you want just to launch it without awaiting it, to not block uselessly other stuff you want to be executed meanwhile the Task is running without waiting for its completion.

Let's see a simplified example:

Inside ViewModel Command:

// Purchase completed
<code to purchase here>

// API Call to send event
await Task.Run(() => { _ = ApiService.PostEvent("purchased"); });

// Navigate Back
<code to navigate back here>

The point is: if you navigate back before the Task has been completed, ViewModel is garbage collected and the Task thread too, so the Task never ends.

How can I prevent that?

Can I run a Task on a thread which will never be destroyed even if its creator is destroyed? Or should I approach in a totally different way?


Solution

  • From the clarifying comments, let's look at a pattern to create the task, perform the navigation immediately, return from the handler, then (optionally) resume to deal with the result of the task. Here, the UI activity is not being blocked while the PostEvent is executing.

     private async void SomeUiElement_Click(object? sender, EventArgs e)
     {
         Task<SomeResult> task = ApiService.PostEvent("purchased");
    
         // WILL EXECUTE IMMEDIATELY
         // Navigate Back
         // < code to navigate back here>
    
         await task;
         if(task.Result is SomeResult valid)
         {
             // Do something with completed task
         }
     }