Tengo una interfaz con algunas funciones asincrónicas.
Los métodos regresan Task
, creo. async
es un detalle de implementación, por lo que no se puede aplicar a métodos de interfaz.
Algunas de las clases que implementan la interfaz no tienen nada que esperar, y algunas pueden simplemente lanzar.
En estos casos, puede aprovechar el hecho de que async
es un detalle de implementación.
Si no tiene nada que hacer await
, puede simplemente regresar Task.FromResult
:
public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
En el caso de lanzar NotImplementedException
, el procedimiento es un poco más prolijo:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
Si tiene muchos métodos lanzando NotImplementedException
(lo que en sí mismo puede indicar que una refactorización a nivel de diseño sería buena), entonces podría resumir la palabra en una clase 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;
}
La clase auxiliar también reduce la basura que el GC tendría que recolectar, ya que cada método con el mismo tipo de retorno puede compartir sus objetos Task
y NotImplementedException
.
Tengo varios otros ejemplos de tipo "constante de tarea" en mi biblioteca AsyncEx .