请考虑以下代码段:
Task[] tasks = new Task[4]; for (var i = 0; i < tasks.Length; ++i) { tasks[i] = Task.Run(async () => { await Task.Delay(4000); }); } for (var i = 0; i < tasks.Length; ++i) await tasks[i]; Console.WriteLine("Done!");
这按预期工作,执行时需要4.000毫秒.但是,如果我Task.Run
用Task.Factory.StartNew
它交换它只需要0.006毫秒!
有谁能解释为什么?
有谁能解释为什么?
简单来说,StartNew
不了解async
代表.
因此,当您的委托首先返回一个不完整的任务时await
,请StartNew
查看委托退出并认为其工作已完成.这就是它返回Task
这里的原因.Task.Run
具有处理异步委托的特殊逻辑,自动解包内部任务.
这只是使用StartNew
异步代码的一个缺陷; 我在博客文章中详细介绍了这个以及其他内容StartNew
是Dangerous.
好的,我在阅读了这篇https://blogs.msdn.microsoft.com/pfxteam/2011/10/24/task-run-vs-task-factory-startnew/后自己找到了答案.
通过在这里使用async关键字,编译器将把这个委托映射为
Func
:调用委托将返回> Task
表示此调用的最终完成.因为代表是Func
,> TResult
是Task
,因此't'的类型将是Task
,而不是> Task
.
所以这段代码按预期工作:
Task[] tasks = new Task[4]; for (var i = 0; i < tasks.Length; ++i) { tasks[i] = Task.Factory.StartNew(async () => { await Task.Delay(4000); }); } for (var i = 0; i < tasks.Length; ++i) await await (tasks[i] as Task); Console.WriteLine("Done!");
哪个也可以使用Unwrap
:
Task[] tasks = new Task[4]; for (var i = 0; i < tasks.Length; ++i) { tasks[i] = Task.Factory.StartNew(async () => { await Task.Delay(4000); }).Unwrap(); } for (var i = 0; i < tasks.Length; ++i) await tasks[i]; Console.WriteLine("Done!");