Temos este método:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
//The thing is that this returns an int to a method that has a return type of Task<int>
return urlContents.Length;
}
Uma conversão implícita ocorre entre Task<int>
e int
? Se não, o que está acontecendo? Como é implementado para funcionar?
async
palavra - chave.Respostas:
Não. Isso é apenas parte de como
async
/await
funciona.Qualquer método declarado como
async
deve ter um tipo de retorno de:void
(evite se possível)Task
(nenhum resultado além da notificação de conclusão / falha)Task<T>
(para um resultado lógico de tipo deT
maneira assíncrona)O compilador faz todo o empacotamento apropriado. A questão é que você está retornando de forma assíncrona
urlContents.Length
- você não pode fazer o método apenas retornarint
, pois o método real retornará quando atingir a primeiraawait
expressão que ainda não foi concluída. Em vez disso, ele retorna umTask<int>
que será concluído quando o próprio método assíncrono for concluído.Observe que
await
faz o oposto - ele desembrulha aTask<T>
em umT
valor, que é como esta linha funciona:... mas é claro que ele desembrulha de forma assíncrona, ao passo que apenas o uso
Result
bloquearia até que a tarefa fosse concluída. (await
pode desembrulhar outros tipos que implementam o padrão aguardado, masTask<T>
é aquele que você provavelmente usará com mais frequência.)Esse empacotamento / desembrulhamento duplo é o que permite que o assíncrono seja tão combinável. Por exemplo, eu poderia escrever outro método assíncrono que chama o seu e duplica o resultado:
(Ou simplesmente, é
return await AccessTheWebAsync() * 2;
claro.)fonte
async
/await
e acho isso extremamente não intuitivo. IMO, deve haver uma palavra-chave ou similar noreturn
para deixar isso claro, por exemploreturn async result;
(da mesma forma queawait result
"desembrulha" oT
doTast<T>
).await
- comT foo = someTaskT;
você obteria "Não é possível converter implicitamente o tipoTask<T>
paraT
" - da mesma forma, eu argumento que faria mais sentido ter uma palavra-chave para o inverso (agrupamentoTask<T>
). Eu sou totalmente a favor da remoção de cotão, mas, neste caso, acho que isso proporciona uma ofuscação desnecessária nosasync
métodos. (Obviamente, a questão é discutível porque os poderes que já falaram / codificaram!)async
, acho que é o suficiente.Não requer a conversão da Tarefa em int. Basta usar o resultado da tarefa.
Ele retornará o valor se disponível, caso contrário, retornará 0.
fonte
Result
; pode causar bloqueios! Considere, por exemplo, este fluxo de trabalho: (1) Escreva uma nota que diz "corte a grama". (2) Espere que a grama seja cortada (3) Coma um sanduíche, (4) Faça o que está escrito na nota ". Com esse fluxo de trabalho, você nunca come um sanduíche ou corta a grama, porque a etapa 2 é uma espera sincronizada em algo que você fará no futuro . Mas esse é o fluxo de trabalho que você está descrevendo aqui.