C# 中的 Foo().Result 和 Task.Run(() => Foo()).Result 有什么区别?

Jan*_*ard 6 c# deadlock asynchronous

在 C# 中,这两个语句有什么区别?如果我在测试类的构造函数中使用第一个,则会出现死锁或类似情况,并且测试永远不会完成。使用第二个代码可以工作。

// Deadlock.
var r = MyMethod().Result;

// Works.
var r = Task.Run(() => MyMethod()).Result;
Run Code Online (Sandbox Code Playgroud)

更新:此提交中有更多上下文:https : //github.com/webCRMdotcom/erp-integrations/pull/92/commits/dd8af89899ce1de837ef6e34f0688a685a5cea3b

Sir*_*ufo 6

区别在于起始线程上下文。

这是一个简单的示例

using System;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        string r;
        OutputThreadInfo("Main");
        r = MyMethod().Result;
        r = Task.Run( () => MyMethod() ).Result;
    }

    public static async Task<string> MyMethod()
    {
        OutputThreadInfo("MyMethod");
        await Task.Delay(50);
        return "finished";
    }

    private static void OutputThreadInfo(string context)
    {
        Console.WriteLine("{0} {1}",context,System.Threading.Thread.CurrentThread.ManagedThreadId);
    }
}
Run Code Online (Sandbox Code Playgroud)

.net 小提琴

这将输出

主要 32
我的方法 32
我的方法 63

MyMethod 的第一次调用将从与 Main 相同的线程开始,如果从具有同步上下文的线程开始,它将被阻塞。

MyMethod 的第二次调用将从不同的线程(线程池中的工作线程)开始,因为 Main 没有同步上下文,因此不会阻塞。

PS 您应该记住,控制台应用程序默认没有同步上下文,但 WinForms、WPF、UWP 应用程序确实有,因此在 async/await 上的行为会有所不同