等待调用异步方法的任务完成而不阻塞线程

时间:2015-09-08 12:26:47

标签: c# async-await task-parallel-library task

我正在尝试连续执行2个任务,但第二个任务在第一个任务完成之前就已经完成,因为它是等待的

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();

我想引出输出

before delay 
after delay 
continued

但我得到

before delay
continued

有没有办法在不占用线程的情况下阻止task1?

2 个答案:

答案 0 :(得分:10)

您的异步lambda会提前返回new Task认为任务已完成。它在第一个await返回。任务构造函数是禁止的!不要使用它(几乎从不)。

它的存在基本上是框架中的设计错误。甚至不应存在未启动的任务,应删除Start方法。我们有TaskCompletionSource

使用Task.Run(async () => ...Task.Run特别支持Task返回功能。

答案 1 :(得分:2)

为了补充@ usr的答案,我认为值得展示如何使现有代码正常运行,并进行以下微小更改:

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();

希望这有助于更好地了解实际的任务工作流程。如果使用得当,Task.Unwrap可以成为电动工具。

那就是说,你确实不需要通过它的构造函数创建一个Task对象。要了解更多信息,请查看TPL的Stephen Toub博客文章: