AFAIK, todo lo que sabe es que en algún momento, es SetResult
oSetException
método está siendo llamado para completar el Task<T>
expuestos a través de su Task
propiedad.
En otras palabras, actúa como el productor de un Task<TResult>
ay su finalización.
Vi aqui el ejemplo:
Si necesito una forma de ejecutar un Func de forma asincrónica y tengo una Tarea para representar esa operación.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Que podría usarse * si no tuviera Task.Factory.StartNew
... Pero sí tengo Task.Factory.StartNew
.
Pregunta:
Por favor alguien puede explicar por ejemplo, un escenario relacionado directamente a TaskCompletionSource
y no a una hipotética situación en la que no tengo Task.Factory.StartNew
?
c#
.net
.net-4.0
task-parallel-library
taskcompletionsource
Royi Namir
fuente
fuente
Respuestas:
Principalmente lo uso cuando solo hay disponible una API basada en eventos ( por ejemplo, sockets de Windows Phone 8 ):
Por lo tanto, es especialmente útil cuando se usa junto con la
async
palabra clave C # 5 .fuente
SomeApiWrapper
se espera en alguna parte, hasta que el editor presente el evento que hace que esta tarea se complete?Microsoft.Bcl.Async
paquete en NuGet que permite lasasync/await
palabras clave en proyectos .NET 4.0 (se recomienda VS2012 y superior).En mi experiencia,
TaskCompletionSource
es ideal para envolver viejos patrones asincrónicos a los modernosasync/await
patrón .El ejemplo más beneficioso que se me ocurre es cuando trabajo
Socket
. Tiene la edad APM y patrones de EAP, pero no losawaitable Task
métodos queTcpListener
yTcpClient
tienen.Personalmente tengo varios problemas con la
NetworkStream
clase y prefiero el crudoSocket
. Siendo que también amo elasync/await
patrón, creé una clase de extensiónSocketExtender
que crea varios métodos de extensiónSocket
.Todos estos métodos se utilizan
TaskCompletionSource<T>
para ajustar las llamadas asincrónicas de la siguiente manera:Paso
socket
elBeginAccept
métodos de modo que consiga un ligero aumento de rendimiento del compilador no tener que levantar el parámetro local.Entonces la belleza de todo:
fuente
Begin.. End...
declaraciones.Para mí, un escenario clásico para usar
TaskCompletionSource
es cuando es posible que mi método no necesariamente tenga que hacer una operación que mucho tiempo. Lo que nos permite hacer es elegir los casos específicos en los que nos gustaría usar un nuevo hilo.Un buen ejemplo de esto es cuando usa un caché. Puede tener un
GetResourceAsync
método, que busca en la memoria caché el recurso solicitado y devuelve de inmediato (sin usar un nuevo hilo, usandoTaskCompletionSource
) si se encontró el recurso. Solo si no se encontró el recurso, nos gustaría usar un nuevo hilo y recuperarlo usandoTask.Run()
.Aquí se puede ver un ejemplo de código: cómo ejecutar un código de forma asincrónica utilizando tareas
fuente
Task.FromResult
para hacer esto. Por supuesto, si está utilizando 4.0 y no tieneTask.FromResult
un TCS para el que usaría, es escribir el suyoFromResult
.Task.FromResult
solo está disponible desde .NET 4.5. Antes de eso, esa era la forma de lograr este comportamiento.Task.Run
, lo que indica que es 4.5+. Y mi comentario anterior abordó específicamente .NET 4.0.En esta publicación de blog , Levi Botelho describe cómo usar el
TaskCompletionSource
para escribir un contenedor asíncrono para un Proceso de modo que pueda iniciarlo y esperar su finalización.y su uso
fuente
Parece que nadie lo mencionó, pero supongo que las pruebas unitarias también se pueden considerar en la vida real .
Me parece
TaskCompletionSource
útil cuando me burlo de una dependencia con un método asíncrono.En el programa real bajo prueba:
En pruebas unitarias:
Después de todo, este uso de TaskCompletionSource parece otro caso de "un objeto Task que no ejecuta código".
fuente
TaskCompletionSource se usa para crear objetos Task que no ejecutan código. En escenarios del mundo real, TaskCompletionSource es ideal para operaciones vinculadas de E / S. De esta manera, obtiene todos los beneficios de las tareas (por ejemplo, valores de retorno, continuaciones, etc.) sin bloquear un hilo durante la operación. Si su "función" es una operación enlazada de E / S, no se recomienda bloquear un hilo usando una nueva Tarea . En cambio, utilizando TaskCompletionSource , puede crear una tarea esclava para indicar cuándo finaliza o falla su operación vinculada de E / S.
fuente
Hay un ejemplo del mundo real con una explicación decente en esta publicación del blog "Programación en paralelo con .NET" . Realmente deberías leerlo, pero de todos modos aquí hay un resumen.
La publicación del blog muestra dos implementaciones para:
La primera implementación mostrada se basa
Task<>
y tiene dos fallas principales. La segunda publicación de implementación continúa para mitigar estos mediante el usoTaskCompletionSource<>
.Aquí está esa segunda implementación:
fuente
await Task.Delay(millisecondsDelay); action(); return;
o (en .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Esto puede simplificar demasiado las cosas, pero la fuente de TaskCompletion permite esperar en un evento. Como tcs.SetResult solo se establece una vez que se produce el evento, la persona que llama puede esperar la tarea.
Mire este video para obtener más información:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
fuente
El escenario del mundo real en el que he utilizado
TaskCompletionSource
es al implementar una cola de descarga. En mi caso, si el usuario inicia 100 descargas, no quiero dispararlas todas a la vez y, en lugar de devolver una tarea estratificada, devuelvo una tarea adjuntaTaskCompletionSource
. Una vez que se completa la descarga, el hilo que está funcionando la cola completa la tarea.El concepto clave aquí es que me estoy desacoplando cuando un cliente solicita que se inicie una tarea desde que realmente se inicia. En este caso porque no quiero que el cliente tenga que lidiar con la gestión de recursos.
tenga en cuenta que puede usar async / await en .net 4 siempre que esté usando un compilador C # 5 (VS 2012+), consulte aquí para obtener más detalles.
fuente
Solía
TaskCompletionSource
ejecutar una tarea hasta que se cancela. En este caso, es un suscriptor de ServiceBus que normalmente quiero ejecutar mientras se ejecuta la aplicación.fuente
TaskCompletionSource
es para tareas comoWaitHandle
es para subprocesos. Y así podemos usarTaskCompletionSource
para realizar una señalización precisa .Un ejemplo es mi respuesta a esta pregunta: ContentDialog retraso después de hacer clic en Aceptar
fuente