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

请考虑以下代码。

static class X { public static int Value = Task.Run(() => 0).Result; } class Program { static void Main(string[] args) { var value = X.Value; } } 

调用Task.Run然后在静态初始值设定项中导致程序永久冻结。 为什么?

您在CLR的类初始化锁定上看到了死锁。

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

僵局。

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

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

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

我认为问题的解释是不正确的。

基本上,在初始化类之前,不能使用类X中的任何内容。


但是Task无法完成,因为它依赖于在类的初始化完成之前不允许运行的方法。

如果是这样,在这种情况下,你应该得到一个编译器错误,但不会在运行时死锁。

无论如何,这段代码是合法的

 static class X { public static int Value = Method(); private static int Method() { return 0; } } 

这是对问题的解释。