I am trying to execute 2 tasks in succession, but the second task is running before the first task has completely finished because it is awaitable
var task1 = new Task(async () =>
{
Trace.WriteLine("before delay");
await Task.Delay(1000);
Trace.WriteLine("after delay");
});
task1.ContinueWith(task => Trace.WriteLine("continued"));
task1.Start();
task1.Wait();
I would like to elicit the output
before delay
after delay
continued
but I get
before delay
continued
Is there a way to block task1 without holding up the thread?
Your async lambda returns early making new Task think the task is done. It returns at the first await. The task constructor is off limits! Don't use it (almost never).
It's existence is basically a design bug in the framework. Unstarted tasks should not even exist and the Start method should be deleted. We have TaskCompletionSource for that.
Use Task.Run(async () => .... Task.Run has special support for Task returning functions.
To complement @usr's answer, I think it's worth showing how to make your existing code work, with these minor changes:
Task<Task> task1 = new Task<Task>(new Func<Task>(async () =>
{
Trace.WriteLine("before delay");
await Task.Delay(1000);
Trace.WriteLine("after delay");
}));
var task2 = task1.Unwrap();
var task3 = task2.ContinueWith(task => Trace.WriteLine("continued"));
task1.Start();
task3.Wait();
Hope this helps to understand the actual task workflow better. Task.Unwrap can be a power tool if used properly.
That said, you indeed should not need to create a Task object via its constructor. To learn more, check TPL's Stephen Toub blog posts:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With