Task.Run(async()=>等待MethodAsync())。Result和MethodAsync()。Result有什么区别? [英] Is there any difference between Task.Run(async () => await MethodAsync()).Result and MethodAsync().Result?
问题描述
我需要实现一个不支持异步的第三方接口,特别是来自automapper的IValueResolver。
I need to implement a third-party interface that doesn't support async, specifically IValueResolver from automapper.
我想知道这两个部分之间有什么区别代码?使用第一个而不是第二个有什么优势吗?我将在MethodAsync()上调用一个外部异步API
I'm wondering what's the difference between these two pieces of code? Is there any advantage of using the first instead of the second? I will call an external async API on MethodAsync()
会同时锁定线程还是仅锁定第二个线程?
Will both lock the thread or just the second?
1
var myValue = Task.Run(async () => await MethodAsync()).Result;
2
var myValue = MethodAsync().Result;
推荐答案
1)
var myValue = Task.Run(async () => await MethodAsync()).Result;
异步方法的同步部分 MethodAsync
2)
var myValue = MethodAsync().Result;
异步方法的同步部分 MethodAsync
将在调用方的线程中运行。
The synchronous part of the asynchronous method MethodAsync
will run in the caller's thread.
现在您可能会问,异步方法的同步部分是什么?
同步部分是异步方法中第一个 await
之前的所有内容。
The synchronous part is everything before the first await
inside the asynchronous method.
更准确地说:同步部分是未完成的等待中的第一个 await
之前的所有内容。
More precisely: The synchronous part is everything before the first await
of a non-completed awaitable.
通常同步部分是微不足道的,但是当我们谈论一个未知的外部API时,我们不能100%确定。
Usually the synchronous part is minuscule, but when we talk about an unknown external API we cannot be 100% sure.
在调用者线程或线程中运行阻塞代码之间的区别-pool线程可能不是那么重要。在这两种情况下,调用者的线程都会在异步调用的整个过程中被阻止。第一种方法( Task.Run
)是否提供任何优势?通常添加 Task.Run
来解决死锁问题,当等待
和等待/结果$时很容易发生c $ c>是混合的。如果您出于某种原因在内部使用
await
,或者外部API在内部使用 await
而不使用内部API,则可能会发生此类问题 ConfigureAwait(false)
。在这种情况下,您会立即注意到它,并且可能会对其进行修复。因此,主动使用 Task.Run
的好处是省心。缺点是使用线程池线程来运行该方法的同步部分。在大多数情况下,这部分很小,以微秒为单位,因此如果您遵循简单的方法,就不会感到内。
The difference between running blocking code in the caller's thread or in a thread-pool thread is probably not that important. In both cases the caller's thread will be blocked for the whole duration of the async call. Does the first approach (Task.Run
) offers any advantage? Usually the Task.Run
is added to solve problems of deadlocks, that can easily occur when await
and Wait/Result
are mixed. In your case such problems could occur if you use await
internally for some reason, or the external API uses await
internally without ConfigureAwait(false)
. In that case you'll notice it immediately and you'll probably fix it. So the advantage of using Task.Run
proactively is peace of mind. The disadvantage is that a thread-pool thread is utilized for running the synchronous part of the method. In most cases this part is very small, measured in μsec, so you shouldn't feel guilty if you follow the easy path.
更新:这是第一种方法的示例,还演示了外部方法的同步和异步部分:
Update: Here is an example of the first approach, that also demonstrates the synchronous and the asynchronous part of the external method:
private void Button1_Click(object sender, EventArgs e)
{
this.Text = YourMethod();
}
public static int YourMethod()
{
return Task.Run(async () => await ExternalMethodAsync()).Result;
}
public static async Task<string> ExternalMethodAsync()
{
Thread.Sleep(500); // Synchronous part
await Task.Delay(500).ConfigureAwait(false); // Asynchronous part
return $"Time: {DateTime.Now:HH:mm:ss.fff}";
}
在这种情况下,对 Task.Run的滥用
是多余的,因为外部库遵循使用 ConfigureAwait(false)
等待的良好做法。
In this case the prophilactic use of Task.Run
is redundant because the external library follows the good practice of awaiting with ConfigureAwait(false)
.
这里是第二种方法的示例:
Here is an example of the second approach:
public static int YourMethod()
{
return ExternalMethodAsync().Result;
}
public static async Task<string> ExternalMethodAsync()
{
Thread.Sleep(500); // Synchronous part
await Task.Delay(500); // Asynchronous part
return $"Time: {DateTime.Now:HH:mm:ss.fff}";
}
此代码陷入僵局。如果您请求 Result
,即使外部库中只有一个未配置的顶级 await
也会导致死锁。直接,无需 Task.Run
。
This code deadlocks. Even a single non-configured top-level await
inside the external library will cause a deadlock, if you request the Result
directly, without Task.Run
.
这篇关于Task.Run(async()=>等待MethodAsync())。Result和MethodAsync()。Result有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!