使用Task.Run调用异步方法似乎错了?

我最近遇到了这个由我们为我们工作的承包商编写的代码。 它要么是非常聪明或愚蠢(我认为后者,但我想要第二个意见)。 我不是在await async速度。

基本上它的工作方式如下:

 public bool Send(TemplatedMessageDto message) { return Task.Run(() => SendAsync(message)) .GetAwaiter() .GetResult(); } public async Task SendAsync(TemplatedMessageDto message) { //code doing stuff var results = await _externalresource.DothingsExternally(); //code doing stuff } 

现在据我所知,第一个Task.Run()是没有意义且效率低下的? 应该是:

 public bool Send(TemplatedMessageDto message) { return SendAsync(message)) .GetAwaiter() .GetResult(); } public async Task SendAsync(TemplatedMessageDto message) { //code doing stuff var results = await _externalresource.DothingsExternally(); //code doing stuff } 

我也不相信这真的是一种异步方法,因为它仍然会等待,对吧? 我认为唯一的优势(甚至是重写)就是释放主要的工作者线程。

有人可以确认第一个任务不应该存在吗?

我也不相信这真的是一种异步方法,因为它仍然会等待,对吧?

正如尤瓦尔解释的那样,它不是。 您不应该使用同步异步。

现在据我所知,第一个Task.Run()是没有意义且效率低下的?

不是真的,以这种方式使用Task.Run是有价值的。

由于您在异步方法上阻塞(您不应该这样做),因此您可能会陷入僵局。 这种情况发生在你有一个SynchronizationContext UI应用程序和asp.net中。

使用Task.Run清除SynchronizationContext因为它将工作卸载到ThreadPool线程并消除死锁的风险。

因此,阻塞是不好的,但如果您最终使用Task.Run更安全。

我也不相信这真的是一种异步方法,因为它仍然会等待,对吧?

您的承包商所做的是使用异步反模式同步 。 他可能这样做是为了避免创建一个同步完成其工作的附加方法。 他不必要地调用Task.Run并使用GetResult立即阻止它。

使用GetAwaiter().GetResult()将传播内部exception(如果发生这种情况),而不是包装的AggregateException

我认为唯一的优势(甚至是重写)就是释放主要的工作者线程。

您的版本和他的将在执行时阻止主线程,而他的也将通过使用线程池线程来执行此操作。 正如Bar所提到的,这可以帮助避免与同步上下文编组有关的问题的死锁。 如果需要,我建议创建一个同步等效项。