【发布时间】:2018-05-22 08:32:25
【问题描述】:
这是一个 linqpad 示例,展示了在短暂延迟后异步执行方法的两种方式。这两个例子似乎都做了同样的事情。我通常会实现第一个版本(使用 Task.Delay.ContinueWith),但我也看到了使用的第二个实现(异步等待)。这两种实现之间有什么区别吗?此场景的工作 Linqpad 示例:
void Main()
{
// Using Task.Delay.ContinueWith...
Task.Delay(1000).ContinueWith(t => DoSomething());
// ... vs async await. Note that I'm not awaiting the task here
DoSomethingAsync();
}
public void DoSomething()
{
"Doing Something...".Dump();
}
public async Task DoSomethingAsync()
{
await Task.Delay(1000);
"Doing Something...".Dump();
}
阅读这篇博文https://blogs.msdn.microsoft.com/pfxteam/2012/03/24/should-i-expose-asynchronous-wrappers-for-synchronous-methods/ 后,我认为第一个实现是“正确”的,因为“DoSomethingAsync()”实际上只是将方法卸载到线程池,并且博文指出:
“不应仅仅为了卸载目的而公开异步方法:同步方法的使用者可以通过使用专门针对异步处理同步方法的功能(例如 Task.Run)轻松实现这些好处。”
但是,StackOverflow 上的这个答案提出了第二种解决方案:
这两种实现之间有什么实际区别吗?如果“异步等待”实现也有效(或更正确),返回的任务应该怎么做?我真的不想等待它,这是一个即发即弃的操作,但我也想处理任何可能引发的异常。
在第一个实现中,我知道我可以使用 ContinueWith, OnlyOnFaulted 来处理异常。
【问题讨论】:
-
如果不在线程池上,您认为您的延续在选项 1 下运行在哪里?
-
ContinueWith 委托将在与原始任务相同的线程上运行,因为它只是它的延续。如果您使用 await 它将使用另一个线程池线程作为其不同的任务。您可以通过输出 Thread.CurrentThread.ManagedThreadId 来检查这一点。
-
DoSomethingAsync返回一个任务,ContinueWith也是如此。 -
@Damien_The_Unbeliever - 我知道 ContinueWith 将在 ThreadPool 线程上运行。这就是我真正想要的。
标签: c# asynchronous async-await task-parallel-library