async await return Task

131

Может кто-нибудь объяснить, что это значит для синхронного метода? Если я попытаюсь изменить метод, asyncVS будет жаловаться на это.

Это работает:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

Это не работает:

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

В общем, я хотел бы знать, что именно это означает: Task.FromResult<object>(null);

Дэвид Дьюри
источник
1
Также прочтите MSDN: msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx .
Патрик Хофман,
@LB хм, работает! Но также, если я просто return;работаю ...!
Дэвид Дьюри
2
«не работает» - не очень хорошее описание того, что не работает. Какое сообщение об ошибке вы получаете?
Джон Кёрнер
@JohnKoerner Я думаю, что довольно очевидно, что компилятор может выдать вам ту же ошибку, как если бы вы пытались вернуть значение в voidфункции.
binki

Ответы:

237

asyncметоды отличаются от обычных методов. Все, что вы возвращаете из asyncметодов, завернуто в файл Task.

Если вы не вернете значение (void), оно будет обернуто Task, если вы вернетесь, intоно будет обернуто Task<int>и так далее.

Если ваш асинхронный метод должен возвращать, intвы должны отметить возвращаемый тип метода как, Task<int>и вы вернете простой, а intне Task<int>. Компилятор будет преобразовывать intв Task<int>вас.

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

Таким же образом, когда вы Task<object>возвращаете тип возврата вашего метода, должен бытьTask<Task<object>>

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

Поскольку ваш метод возвращается Task, он не должен возвращать никакого значения. В противном случае он не будет компилироваться.

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

Имейте в виду, что асинхронный метод без awaitоператора - нет async.

Шрирам Шакхивел
источник
1
Для меня этот тип возврата не работает (думаю, я что-то делаю не так). Пример статической асинхронной задачи <string> DoStuff () {... = await SomeMethodAsync (); вернуть «строковое значение»; } .. var x = DoStuff (); Но этот x - с типом «Task <string>», а не с типом «string» ... Почему так?
Prokurors
3
@Prokurors Тебе тоже нужно подождать DoStuff(). Например:var x = await DoStuff();
Шрирам Сакхивел
5
Должно бытьreturn await Task.FromResult<object>(null);
sandeep talabathula
@sandeeptalabathula, что равно return null
Шрирам Сакхивел,
2
@ProfK Task.WhenAny- пример.
Servy 01
55

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

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

Вот пример без возвращаемого значения:

public async Task MethodName()
{
    await Task.CompletedTask;
}

Прочтите это:

TPL: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx и Задачи: http://msdn.microsoft.com/en-us/library/system.threading .tasks (v = vs.110) .aspx

Асинхронный: http://msdn.microsoft.com/en-us/library/hh156513.aspx Ожидание: http://msdn.microsoft.com/en-us/library/hh156528.aspx

Крупный
источник
9
Вы можете просто вернуться nullнапрямую, не дожидаясь фиктивной задачи.
Ли
5
@Lee, но если вы это сделаете, компилятор пожалуется ( asyncвыдаст предупреждение), что метод будет выполняться асинхронно, с предложением использовать awaitключевое слово где-нибудь в методе. Я предлагаю просто использовать return Task.FromResult((object)null);и удалить asyncключевое слово, чтобы уменьшить предупреждающий шум компилятора.
binki
Да, я пробовал просто использовать returnв Задаче, но задача продолжает выполняться, потому что returnне возвращаетTask
Тернер Басс
30

Добавление ключевого слова async - это просто синтаксический сахар, упрощающий создание конечного автомата. По сути, компилятор берет ваш код;

public async Task MethodName()
{
     return null;
}

И превращает его в;

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

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

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

См. Что генерирует async & await? для кровавого примера.

Этот процесс имеет много общего с тем, как компилятор обрабатывает методы итератора с помощью операторов yield.

Джереми Лейкман
источник
2

Это задача, которая возвращает задачу типа String (анонимная функция C # или, другими словами, используется делегирование Func)

    public static async Task<string> MyTask()
    {
        //C# anonymous AsyncTask
        return await Task.FromResult<string>(((Func<string>)(() =>
        {
            // your code here
            return  "string result here";

        }))());
    }
Адель Мурад
источник
1
При размещении кода в качестве ответа, пожалуйста, включите некоторое объяснение того, что вы демонстрируете. В этом случае вы добавляете ответ на старый вопрос, на который уже есть несколько ответов. Добавьте одно или два предложения, описывающих, что демонстрирует ваш новый ответ, чего еще не было в других ответах. Я не говорю, что с вашим ответом что-то не так, я просто прошу вас помочь другим, выразив словами то, что вы показываете своим кодом.
ToolmakerSteve
0

Чтобы получить правильные ответы от асинхронных методов, вам нужно поставить await при вызове этих методов задачи. Это будет ждать преобразования его обратно в тип возвращаемого значения, а не в тип задачи.

Например, var content = await StringAsyncTask (

где public async Task < String > StringAsyncTask ())

Abhiroop Mukherjee
источник