Fen*_*ari 4 .net c# task task-parallel-library async-await
任何人都可以解释一下,也许我错过了一些明显的东西.
这两个案例的行为似乎相同,但事实并非如此.
案例1:
用async Action,一段时间做一些工作来启动一个任务:
var t = Task.Run(async () => { await Task.Delay(2000); });
Run Code Online (Sandbox Code Playgroud)第二个任务等待第一个任务:
var waitingTask = Task.Run(() => { t.Wait(); });
Run Code Online (Sandbox Code Playgroud)等待第二个任务:
waitingTask.Wait();
Run Code Online (Sandbox Code Playgroud)案例2:
Task使用Task构造函数构建一个,传递相同的async Action:
var t = new Task(async () => { await Task.Delay(2000); });
Run Code Online (Sandbox Code Playgroud)启动另一个任务以等待第一个任务(就像在第一个案例中一样):
var waitingTask = Task.Run(() => { t.Wait(); });
Run Code Online (Sandbox Code Playgroud)开始第一项任务:
t.Start();
Run Code Online (Sandbox Code Playgroud)等待第二个任务:
waitingTask.Wait();
Run Code Online (Sandbox Code Playgroud)第一种情况表现如预期:等待任务在第一种情况结束后,在2秒后结束.
第二种情况很奇怪:等待任务很快就会结束,早在第一种情况发生之前.
从两个任务打印消息时很容易看到.第二个任务结束时的打印将显示差异.
我正在使用VS 2015 Preview,它可能使用Roslyn进行编译,如果这很重要的话.
答案在这里http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
实际上,问题是,当你试图给出一个时new Task,它只能带Action一个Func<Task>.以下是前两行,但使用正确的重载进行了重写.
Task t = Task.Run(async () => { await Task.Delay(2000); });
Run Code Online (Sandbox Code Playgroud)
和
Task<Task> t = new Task<Task>(async () => { await Task.Delay(2000); });
Run Code Online (Sandbox Code Playgroud)
第一个按预期创建任务.第二个创建一个任务,谁的返回类型是一个等待2000毫秒的任务.第一个例子是因为以下重载...
public Task Run(Func<Task>);
public Task<T> Run(Func<T>);
public Task<T> Run(Func<Task<T>>);
etc...
Run Code Online (Sandbox Code Playgroud)
这些重载旨在Task<Task<T>>.Unwrap()为您自动调用.
结果是在您的第二个示例中,您实际上正在等待第一个任务的开始/排队.
您可以通过修复第二个示例
var t = new Task<Task>(async () => { await Task.Delay(2000); }).Unwrap();
Run Code Online (Sandbox Code Playgroud)