Почему асинхронная функция без ожидания приводит к предупреждению компилятора?

Может ли кто-нибудь объяснить, почему асинхронные функции в С # 5 должны иметь хотя бы 1 ожидание? Я не могу найти четкой причины / объяснения.

Под обязательным я подразумеваю, что компилятор предупреждает, когда асинхронная функция не имеет внутри себя вызовов ожидания, но не выдает ошибку компиляции.

Из этого ответа:

Точно так же метод, помеченный как async, должен иметь хотя бы одно ожидание. При ожидании среда выполнения сохранит состояние текущего потока и стек вызовов, выполнит асинхронный вызов и вернется к циклу сообщений среды выполнения, чтобы обработать следующее сообщение и сохранить реакцию приложения. Когда асинхронная операция завершена, при следующей возможности планирования стек вызовов для выполнения асинхронной операции вставляется обратно и продолжается, как если бы вызов был синхронным.

Но из msdn:

Если метод не содержит выражения или оператора ожидания, он выполняется синхронно. Предупреждение компилятора предупреждает вас о любых асинхронных методах, которые не содержат await, потому что такая ситуация может указывать на ошибку.

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


person xdumaine    schedule 11.04.2013    source источник
comment
Разве он не несколько раз спрашивал-отвечал раньше?   -  person Gennady Vanin Геннадий Вани&    schedule 11.04.2013


Ответы (1)


В MSDN есть хорошее описание этого предупреждения: Предупреждение компилятора (уровень 1) CS4014 < / а>. Хорошая цитата из него будет:

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

Я думаю, что основная причина, по которой существует это предупреждение, заключается в том, что async / await не совсем очевиден, и разработчики обычно допускают ошибки, которые я опишу ниже.

Например, у вас есть метод, который делает что-то тяжелое в течение нескольких секунд:

public int DoSomething()
{
    int sum = 0;

    for (int i = 0; i < 10; i++)
    {
        sum += i;
        Thread.Sleep(1000);
    }

    return sum;
}

Вы где-то слышали о async и await и хотите их попробовать. И вот как очень часто люди думают, что они переместят все в фоновый режим (может быть, не часто, но я думал, что это так, прежде чем я прочитал больше документации, чтобы мы могли посчитать по крайней мере меня):

public async Task<int> DoSomething()
{
    int sum = 0;

    for (int i = 0; i < 10; i++)
    {
        sum += i;
        Thread.Sleep(1000);
    }

    return sum;
}

Вы думаете, что проблема решена, но предупреждение говорит вам, что без await вы не должны использовать async, потому что он просто ничего не делает, весь ваш код будет выполняться синхронно, последний образец с async аналогичен следующему коду:

public Task<int> DoSomething()
{
    int sum = 0;

    for (int i = 0; i < 10; i++)
    {
        sum += i;
        Thread.Sleep(1000);
    }

    return Task.Result<int>(sum);
}

Где вы все делаете в том же контексте, в котором вызывается этот метод.

Итак, основная причина этого предупреждения, я думаю, состоит в том, чтобы дать людям понять, что они, вероятно, используют async неправильно, и сейчас самое время прочитать документацию.

person outcoldman    schedule 11.04.2013