我可能会遗漏一些东西但是做什么之间有什么不同:
public void MyMethod()
{
Task t = Task.Factory.StartNew(DoSomethingThatTakesTime);
t.Wait();
UpdateLabelToSayItsComplete();
}
public async void MyMethod()
{
var result = Task.Factory.StartNew(DoSomethingThatTakesTime);
await result;
UpdateLabelToSayItsComplete();
}
private void DoSomethingThatTakesTime()
{
Thread.Sleep(10000);
}
6 回答
你是 .
你在餐厅的服务员点了午餐 . 在给出订单后的一刻,一位朋友走进来,坐在你身边,开始交谈 . 现在你有两个选择 . 你可以忽略你的朋友,直到任务完成 - 你可以等到你的汤到来,在你等待的时候什么都不做 . 或者你可以回复你的朋友,当你的朋友停止说话时,服务员会给你带来汤 .
Task.Wait
阻塞,直到任务完成 - 您将忽略您的朋友,直到任务完成 .await
继续处理消息队列中的消息,当任务完成时,它会将消息排入"pick up where you left off after that await" . 你和你的朋友谈话,当谈话休息时,汤就到了 .为了演示Eric的答案,这里有一些代码:
这个例子非常清楚地展示了这种差异使用async / await,调用线程不会阻塞并继续执行 .
DoAsTask输出:
DoAsAsync输出:
更新:通过在输出中显示线程ID来改进示例 .
Wait(),将导致以同步方式运行潜在的异步代码 . 等待不会 .
例如,您有一个asp.net Web应用程序 . UserA调用/ getUser / 1 endpoints . asp.net app pool将从线程池(Thread1)中选择一个线程,并且该线程将进行http调用 . 如果你执行Wait(),这个线程将被阻塞,直到http调用解析 . 在等待时,如果UserB调用/ getUser / 2,那么app pool将需要服务另一个线程(Thread2)再次进行http调用 . 你刚刚创建了(好吧,实际从app池中获取)另一个线程,因为你无法使用Thread1它被Wait()阻止了 .
如果在Thread1上使用await,则SyncContext将管理Thread1和http调用之间的同步 . 简单地说,一旦http呼叫完成,它将通知 . 同时,如果UserB调用/ getUser / 2,那么,你将再次使用Thread1进行http调用,因为它一旦被等待就被释放了 . 然后另一个请求可以使用它,甚至更多 . 一旦http调用完成(user1或user2),Thread1就可以获得结果并返回调用者(客户端) . Thread1用于多个任务 .
在这个例子中,实际上并不多 . 如果您正在等待在不同线程上返回的任务(如WCF调用)或放弃对操作系统的控制(如文件IO),则await将通过不阻塞线程来使用较少的系统资源 .
在上面的示例中,您可以使用“TaskCreationOptions.HideScheduler”,并大大修改“DoAsTask”方法 . 该方法本身不是异步的,因为它与“DoAsAsync”一起发生,因为它返回“任务”值并标记为“异步”,进行了几种组合,这就是它给我与使用“async / await”完全相同的方式: