等待调用异步方法的任务完成而不阻塞线程
wait for a Task that calls an async method to complete without blocking thread
我正在尝试连续执行 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?
你的异步 lambda returns 提前让 new Task
认为任务已经完成。它 returns 在第一个 await
。任务构造函数是禁区!不要使用它(几乎从不)。
它的存在基本上是框架的设计错误。甚至不应该存在未启动的任务,并且应该删除 Start
方法。为此,我们有 TaskCompletionSource
。
使用Task.Run(async () => ...
。 Task.Run
对 Task
返回函数有特殊支持。
为了补充@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 博客文章:
我正在尝试连续执行 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?
你的异步 lambda returns 提前让 new Task
认为任务已经完成。它 returns 在第一个 await
。任务构造函数是禁区!不要使用它(几乎从不)。
它的存在基本上是框架的设计错误。甚至不应该存在未启动的任务,并且应该删除 Start
方法。为此,我们有 TaskCompletionSource
。
使用Task.Run(async () => ...
。 Task.Run
对 Task
返回函数有特殊支持。
为了补充@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 博客文章: