Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async in Task ContinueWith behavior?

How could you explain the following behaviour:

await Task.Run(() => { }).ContinueWith(async prev =>
{
    Console.WriteLine("Continue with 1 start");
    await Task.Delay(1000);
    Console.WriteLine("Continue with 1 end");
}).ContinueWith(prev =>
{
    Console.WriteLine("Continue with 2 start");
});

Why will we get “Continue with 2 start” before “Continue with 1 end”?

like image 526
Vladyslav Furdak Avatar asked Aug 15 '26 02:08

Vladyslav Furdak


1 Answers

ContinueWith doesn't know anything about async and await. It doesn't expect a Task result so doesn't await anything even if it gets one. await was created as a replacement for ContinueWith.

The cause of the problem is that ContinueWith(async prev => creates an implicit async void delegate. ContinueWith has no overload that expects a Task result, so the only valid delegate that can be created for ContinueWith(async prev => question's code is :

async void (prev) 
{
    Console.WriteLine(“Continue with 1 start”);
    await Task.Delay(1000);
    Console.WriteLine(“Continue with 1 end”);
}

async void methods can't be awaited. Once await Task.Delay() is encountered, the continuation completes, the delegate yields and the continuation completes. If the application exits, Continue with 1 end may never get printed. If the application is still around after 1 second, execution will continue.

If the code after the delay tries to access any objects already disposed though, an exception will be thrown.

If you check prev.Result's type, you'll see it's a System.Threading.Tasks.VoidTaskResult. ContinueWith just took the Task generated by the async/await state machine and passed it to the next continuation

like image 59
Panagiotis Kanavos Avatar answered Aug 16 '26 17:08

Panagiotis Kanavos