Quiero crear un completado Task
(no Task<T>
). ¿Hay algo integrado en .NET para hacer esto?
Una pregunta relacionada: Crear una tarea completada <T>
fuente
Quiero crear un completado Task
(no Task<T>
). ¿Hay algo integrado en .NET para hacer esto?
Una pregunta relacionada: Crear una tarea completada <T>
La versión más reciente de .Net (v4.6) está agregando justamente eso, una tarea incorporada .
Task completedTask = Task.CompletedTask;
Esa propiedad se implementa como un singleton sin bloqueo, por lo que casi siempre usaría la misma tarea completada.
Task.CompletedTask
todavía es interno.
Task<T>
es implícitamente convertible a Task
, así que solo obtenga un completado Task<T>
(con T
cualquier valor) y úselo. Puede usar algo como esto para ocultar el hecho de que un resultado real está allí, en alguna parte.
private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
return completedTask;
}
Tenga en cuenta que dado que no estamos exponiendo el resultado, y la tarea siempre se completa, podemos almacenar en caché una sola tarea y reutilizarla.
Si está utilizando .NET 4.0 y no lo tiene FromResult
, puede crear el suyo usandoTaskCompletionSource
:
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
Mi método preferido para hacer esto es llamar Task.WhenAll()
sin argumentos. La documentación de MSDN establece que "Si la matriz / enumerable suministrada no contiene tareas, la tarea devuelta pasará inmediatamente a un estado RanToCompletion antes de que se devuelva al llamante". Eso suena como lo que quieres.
Actualización: encontré la fuente en la Fuente de referencia de Microsoft ; allí puede ver esa tarea. Cuando todo contiene lo siguiente:
return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
Task.CompletedTask :
new WhenAllPromise(tasks);
Entonces Task.CompletedTask es de hecho interno, pero se expone llamando a WhenAll () sin argumentos.
Me gustaría utilizar Task.Delay(0)
. Internamente, devuelve una instancia en caché de un completado Task<T>
. Esto es exactamente lo que la respuesta actual sugiere hacer de todos modos, solo que ahora no tiene que almacenar en caché una instancia usted mismo, ni tiene valores de basura poco elegantes en su código.
Tal vez pienses que puedes usar Task.Yield()
, pero resulta que el resultado de noTask.Yield()
es un subtipo de , mientras que el resultado de es. Esa es una de las diferencias sutiles entre los dos.Task
Task.Delay(0)
Puede usar Task.FromResult (en .NET 4.5) para devolver un archivo completadoTask<T>
.
Si necesita un no genérico Task
, siempre puede usar Task.FromResult(0)
o similar, ya que Task<T>
es una subclase de Task
.
Para uso .Net 4.6 y superior
return Task.CompletedTask;
Para la versión inferior puedes usar
return new Task(() => { });
return Task.Delay(0);
lugar?
Puede usar Nito.AsyncEx.TaskConstants.Completed de una gran biblioteca AsyncEx de Stephen Cleary .
Qué tal si:
#pragma warning disable 1998
public async Task emptyTask() {
}
#pragma warning restore 1998
Puede omitir la supresión de advertencia si no le importa.
async
todavía crea todo el aparato de máquina de estado, incluso si no lo usa, por lo que devolver una tarea vacía es más eficiente para escenarios de bajos recursos.
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.
¿Qué problemas crees que tiene esto? Si almacena un solo caché,Task
todo su programa ocupa un bit adicional de memoria. Eso es nada . Además, uno podría crear una tarea completa sin hacer eso, simplemente no sería mejor.ValueTask
tareas completadas (es decir, valores que ya tiene para que el código sea esencialmente sincrónico), lo que le ahorrará una asignación.