我需要知道这些记录中是否有差异,如果有,它们是什么? 对我来说很困难:
1) Task.Run(async () => { await CheckVerification(); });
2) Task.Run(() => CheckVerification());
3) await Task.Run(async () => { await CheckVerification(); });
答案 0 :(得分:0)
如果我们忘记Task.Run
一秒钟,也许更容易理解它们之间的区别。第一点和第二点之间的区别基本上与等待或仅从Task
返回方法返回内部任务相同:
// 1)
public async Task WithAwait() => await SomeOtherTaskReturningMethod();
// 2)
public Task WithoutAwait() => return SomeOtherTaskReturningMethod();
第一个创建另一个任务,该任务包装内部任务,这是一个很小的开销,但是在其他方面,这两种方法在功能上几乎相同。一个小的区别是,当SomeOtherTaskReturningMethod
引发异常时,内部任务的AggregatedException
将被解包,并且(第一个)内部异常将被进一步引发。当然,事情仍然取决于外部任务发生了什么。在您的第3点上,它也在等待中,因此您将从外部任务(如果有)中获得未包装的异常,而第1和第2个示例只是开火而忘却。
现在,让我们再次考虑Task.Run
。主要问题是,当您也可以简单地调用Task
并获得相同结果时,为什么此方法具有重载,它们接受Task
(实际上是await CheckVerification();
个返回的回调)? (我知道这不是问题的一部分,但也许值得澄清)
因此存在Task.Run
重载的原因是,Task
返回方法本身不一定在另一个线程上执行(我建议this reading)。例如,它可以仅通过网络套接字发送一条消息并返回一个Task
,当收到特定答案时,将完成此操作。这使操作异步,但仍不是多线程的。
如果您有这样的任务,并且希望将其强制在另一个线程上执行,那么您可以通过Task.Run
执行该任务,该命令将使用默认调度程序,并最终在池线程上执行您的任务。
值得一提的是,这是一种非常罕见的情况。在大多数情况下,您应该依靠Task
返回方法的内部实现。
TL; DR:
所以我认为真正的问题是是否
await CheckVerification();
或
await Task.Run(() => CheckVerification());
是更好的解决方案(或者其中一种不带await
的解雇模式)。在大多数情况下,我会投票赞成第一个选项,但是如果您确实有信心必须将CheckVerification
返回的任务分配给一个池线程(无论是否在内部执行),那么第二个选项也可以有道理。
答案 1 :(得分:-1)
1)开始任务。该任务将等待内部的方法,但会异步进行,因此您的UI或调用线程将不会阻塞。
2)启动一个任务,再启动另一个任务。一切都异步运行,什么都没有等待,完全着火而忘记了。
3)将启动一个任务,该任务启动一个方法并等待它,返回执行上下文,让调用线程以其等待状态释放执行上下文,让调用此方法的方法继续执行,直到等待它为止方法。