Подтвердить что ты не робот

Задание. Запуск в статическом инициализаторе

Рассмотрим следующий код.

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

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

Вызов Task.Run, а затем Result в статическом инициализаторе заставляет программу постоянно замирать. Почему?

4b9b3361

Ответ 1

Вы видите тупик в блокировке инициализации класса CLR.

В принципе, ничто в классе X не может использоваться до тех пор, пока класс не будет инициализирован. Но ваш анонимный метод () => 0 скомпилирован для члена класса. Инициализация класса не будет завершена до тех пор, пока Task не завершится, но Task не сможет завершить, так как зависит от метода, который не разрешен для запуска до завершения инициализации класса.

Тупик.

Ваш пример явно надуман, поэтому невозможно дать совет относительно того, как исправить вашу реальную проблему. В этом конкретном примере вы можете заменить инициализацию на Task.FromResult(0).Result;, но, конечно, это еще более надуманное; если бы это было действительно полезно, вы просто назначили 0 этому полю.

Но каков бы ни был ваш реальный сценарий, способ исправить это - это не создать ситуацию, при которой инициализация класса зависит от какого-то внешнего компонента, требующего завершения этого класса. Например, вы можете использовать Lazy<T> для инициализации значения или просто вызвать метод напрямую (что будет разрешено).

Если изобретен какой-либо пример или нет, никогда не начинайте Task начинать только немедленно блокировать текущий поток до его завершения. Поэтому, если у вас есть какой-либо код, который, хотя и не совсем точно такой же, как этот пример, по-прежнему делает то же самое, очевидное исправление заключается в том, чтобы изменить его для выполнения в последовательном однопоточном режиме.

Ответ 2

Я думаю, что объяснение проблемы неверно.

В принципе, ничто в классе X не может использоваться до тех пор, пока класс не будет инициализирован.


но Задача не может быть выполнена, поскольку она зависит от метода, который не является разрешено работать до завершения инициализации класса.

если это так, в этом случае вы должны получить ошибку компилятора, но не тупик во время выполнения.

В любом случае, этот код является законным

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

Здесь объясняется проблема.