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