静态初始化程序中的Task.Run

Tim*_*lds 13 .net c# task-parallel-library .net-4.5

请考虑以下代码.

static class X
{
    public static int Value = Task.Run(() => 0).Result;
}

class Program
{
    static void Main(string[] args)
    {
        var value = X.Value;
    }
}
Run Code Online (Sandbox Code Playgroud)

调用Task.Run然后Result在静态初始化程序中导致程序永久冻结.为什么?

Pet*_*iho 14

你在CLR的类初始化锁上看到了死锁.

基本上,在X类初始化之前,类中没有任何东西可以使用.但是您的匿名方法() => 0被编译为该类的成员.类可以在完成之前完成类初始化Task,但是Task无法完成,因为它依赖于在类的初始化完成之前不允许运行的方法.

僵局.

你的例子显然是人为的,所以不可能就如何解决你的现实问题提供建议.在这个特定的例子中,您可以替换初始化,Task.FromResult(0).Result;但当然这更加做作; 如果它实际上可用,你只需要分配0到该字段.

但无论您的实际情况如何,修复它的方法是不要创建一种情况,其中类的初始化取决于需要该类来完成的某些外部组件.例如,您可以考虑使用Lazy<T>初始化值,或者直接调用该方法(这是允许的).

无论一个例子是否有人工作,开始一个Task只是立即阻止当前线程直到它完成为止是没有任何意义的.因此,如果你有任何代码,虽然不完全像这个例子,但仍然有效地做同样的事情,显而易见的解决方法是将其更改为以串行,单线程方式执行.