Task.Run(async()=>等待MethodAsync())。Result和MethodAsync()。Result有什么区别? [英] Is there any difference between Task.Run(async () => await MethodAsync()).Result and MethodAsync().Result?

查看:143
本文介绍了Task.Run(async()=>等待MethodAsync())。Result和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 来解决死锁问题,当等待等待/结果是混合的。如果您出于某种原因在内部使用 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()=&gt;等待MethodAsync())。Result和MethodAsync()。Result有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆