Tarefa assíncrona espera retorno

131

Alguém pode explicar o que isso significa em um método síncrono? Se eu tentar mudar o método async, o VS reclamará.

Isso funciona:

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

Isso não funciona:

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

Então, basicamente, eu gostaria de saber o que exatamente isso significa: Task.FromResult<object>(null);

David Dury
fonte
1
Além disso, leia o MSDN: msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx .
Patrick Hofman
@LB hmm que funciona! Mas também se eu apenas return;funcionar também ...!
David Dury
2
"não funciona" não fornece uma descrição muito boa do que não está funcionando. Qual é a mensagem de erro que você recebe?
John Koerner
@ JohnKoerner Eu acho que é bastante óbvio que o compilador pode fornecer o mesmo erro como se você tentasse retornar um valor em uma voidfunção.
binki

Respostas:

236

asyncmétodos são diferentes dos métodos normais. O que você retornar dos asyncmétodos está envolvido em um Task.

Se você não retornar nenhum valor (nulo), ele será quebrado Task, se você retornar int, será quebrado Task<int>e assim por diante.

Se seu método assíncrono precisar retornar, intmarque o tipo de retorno do método como Task<int>e você retornará sem inta opção Task<int>. Compilador irá converter o intque Task<int>para você.

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

Da mesma forma, quando você retorna Task<object>, o tipo de retorno do método deve serTask<Task<object>>

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

Como seu método está retornando Task, ele não deve retornar nenhum valor. Caso contrário, não será compilado.

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

Lembre-se de que o método assíncrono sem uma awaitdeclaração não é async.

Sriram Sakthivel
fonte
1
Para mim, esse tipo de retorno não funciona (acho que estou fazendo algo errado). Exemplo de tarefa assíncrona estática <string> DoStuff () {... = aguardar SomeMethodAsync (); retornar "valor da string"; } .. var x = DoStuff (); Mas esse x - é do tipo "Task <string>", não do tipo "string" ... Por que é isso?
Prokurors
3
@ Prokurors Você precisa aguardar DoStuff()também. Por exemplo:var x = await DoStuff();
Sriram Sakthivel
5
Deveria serreturn await Task.FromResult<object>(null);
sandeep talabathula,
@sandeeptalabathula Isso equivale a um valor nulo de retorno
Sriram Sakthivel
2
@ProfK Task.WhenAnyé um exemplo.
#
55

Você precisa usar a palavra-chave wait quando usar async e seu tipo de retorno de função deve ser genérico Aqui está um exemplo com valor de retorno:

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

Aqui está um exemplo sem valor de retorno:

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

Leia estes:

TPL: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx e tarefas: http://msdn.microsoft.com/en-us/library/system.threading .tasks (v = vs.110) .aspx

Assíncrono: http://msdn.microsoft.com/en-us/library/hh156513.aspx Aguardar: http://msdn.microsoft.com/en-us/library/hh156528.aspx

Principal
fonte
9
Você pode simplesmente retornar nulldiretamente em vez de aguardar uma tarefa fictícia.
Lee
5
@ Lee, mas se você fizer isso, o compilador reclama (emite um aviso) que o asyncmétodo será executado de forma assíncrona com uma sugestão de usar a awaitpalavra - chave em algum lugar do método. Sugiro apenas usar return Task.FromResult((object)null);e remover a asyncpalavra-chave para reduzir o ruído de aviso do compilador.
binki
Sim, eu tentei apenas usar returnem uma tarefa, mas a tarefa continua em execução, porque returnnão está retornando umTask
Turner Bass
30

A adição da palavra-chave assíncrona é apenas um açúcar sintático para simplificar a criação de uma máquina de estado. Em essência, o compilador pega seu código;

public async Task MethodName()
{
     return null;
}

E transforma em;

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

Se o seu código tiver alguma awaitpalavra-chave, o compilador deve usar seu método e transformá-lo em uma classe para representar a máquina de estado necessária para executá-lo. Em cada awaitpalavra - chave, o estado das variáveis ​​e a pilha serão preservadas nos campos da classe, a classe se adicionará como um gancho de conclusão à tarefa que você está aguardando e retornará.

Quando essa tarefa for concluída, sua tarefa será executada novamente. Portanto, algum código extra é adicionado à parte superior do método para restaurar o estado das variáveis ​​e pular para a próxima camada do seu código.

Consulte O que async & waitit gera? para um exemplo sangrento.

Esse processo tem muito em comum com a maneira como o compilador lida com métodos do iterador com instruções de rendimento.

Jeremy Lakeman
fonte
2

Esta é uma tarefa que está retornando uma tarefa do tipo String (função anônima C # ou, em outras palavras, uma delegação é usada 'Func')

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

        }))());
    }
Adel Mourad
fonte
1
Ao postar o código como resposta, inclua algumas explicações sobre o que você está demonstrando. Nesse caso, você está adicionando uma resposta a uma pergunta antiga que já possui várias respostas. Adicione uma ou duas frases descrevendo o que sua nova resposta está demonstrando, que ainda não foi mostrada nas outras respostas. Não estou dizendo que algo está errado com sua resposta, apenas pedindo que você ajude outras pessoas, colocando em palavras o que você está mostrando com seu código.
Página Inicial>
0

Para obter respostas adequadas dos métodos assíncronos, é necessário aguardar enquanto chama esses métodos de tarefa. Isso aguardará a conversão para o tipo de valor retornado em vez do tipo de tarefa.

Por exemplo, var content = waitit StringAsyncTask (

onde público assíncrono Tarefa < String > StringAsyncTask ())

abhiroop mukherjee
fonte