Aqui está o que eu quero dizer:
public Task<SomeObject> GetSomeObjectByTokenAsync(int id)
{
string token = repository.GetTokenById(id);
if (string.IsNullOrEmpty(token))
{
return Task.FromResult(new SomeObject()
{
IsAuthorized = false
});
}
else
{
return repository.GetSomeObjectByTokenAsync(token).ContinueWith(t =>
{
t.Result.IsAuthorized = true;
return t.Result;
});
}
}
Acima método pode ser esperado e eu acho que se assemelha ao que o T perguntar-based A síncrona P attern sugere fazer? (Os outros padrões que conheço são os padrões APM e EAP .)
Agora, o que acontece com o seguinte código:
public async Task<SomeObject> GetSomeObjectByToken(int id)
{
string token = repository.GetTokenById(id);
if (string.IsNullOrEmpty(token))
{
return new SomeObject()
{
IsAuthorized = false
};
}
else
{
SomeObject result = await repository.GetSomeObjectByTokenAsync(token);
result.IsAuthorized = true;
return result;
}
}
As principais diferenças aqui são que o método é async
e utiliza as await
palavras-chave - então o que isso muda em contraste com o método escrito anteriormente? Eu sei que isso também pode ser esperado. Qualquer método que retorne Task pode, a menos que eu esteja enganado.
Estou ciente da máquina de estado criada com essas instruções switch sempre que um método é rotulado como async
e sei que await
ele próprio não usa thread - ele não bloqueia nada, o thread simplesmente faz outras coisas, até que seja chamado de volta para continuar a execução do código acima.
Mas qual é a diferença subjacente entre os dois métodos, quando os chamamos usando a await
palavra - chave? Existe alguma diferença e, se houver - qual é a preferida?
EDITAR: Eu sinto que o primeiro trecho de código é o preferido, porque eliminamos efetivamente as palavras-chave async / wait, sem nenhuma repercussão - retornamos uma tarefa que continuará sua execução de forma síncrona ou uma tarefa já concluída no caminho ativo (que pode ser em cache).
result.IsAuthorized = true
ele será executado no pool de encadeamentos, enquanto no segundo exemplo, ele poderá ser executado no mesmo encadeamento que foi chamadoGetSomeObjectByToken
(se houvesse umSynchronizationContext
instalado nele, por exemplo, era um encadeamento da interface do usuário). O comportamento seGetSomeObjectByTokenAsync
lança uma exceção também será um pouco diferente. Em geral,await
prefere-seContinueWith
, pois quase sempre é mais legível.