Eu tenho uma interface com algumas funções assíncronas.
Métodos retornando Task
, eu acredito. async
é um detalhe de implementação, portanto, não pode ser aplicado a métodos de interface.
Algumas das classes que implementam a interface não têm nada a esperar, e algumas podem apenas lançar.
Nesses casos, você pode tirar vantagem do fato de que async
é um detalhe de implementação.
Se você não tiver nada para fazer await
, pode simplesmente retornar Task.FromResult
:
public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
No caso de arremesso NotImplementedException
, o procedimento é um pouco mais prolixo:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
Se você tiver muitos métodos de lançamento NotImplementedException
(o que por si só pode indicar que alguma refatoração no nível de design seria boa), você poderia resumir o prolixo em uma classe auxiliar:
public static class TaskConstants<TResult>
{
static TaskConstants()
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetException(new NotImplementedException());
NotImplemented = tcs.Task;
}
public static Task<TResult> NotImplemented { get; private set; }
}
public Task<int> Fail() // note: no "async"
{
return TaskConstants<int>.NotImplemented;
}
A classe auxiliar também reduz o lixo que o GC teria que coletar, uma vez que cada método com o mesmo tipo de retorno pode compartilhar seus objetos Task
e NotImplementedException
.
Tenho vários outros exemplos de tipo de "constante de tarefa" em minha biblioteca AsyncEx .