简体   繁体   中英

wait for a Task that calls an async method to complete without blocking thread

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM