Si no desea usar async / await dentro de su método, pero aún así "decorarlo" para poder usar la palabra clave wait desde afuera, TaskCompletionSource.cs :
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;
}
De aquí y de aquí
Para soportar tal paradigma con las Tareas, necesitamos una forma de retener la fachada de la Tarea y la capacidad de referirnos a una operación asincrónica arbitraria como Tarea, pero para controlar la vida útil de esa Tarea de acuerdo con las reglas de la infraestructura subyacente que proporciona el asincronía, y hacerlo de una manera que no cueste mucho. Este es el propósito de TaskCompletionSource.
Vi que también se usa en la fuente .NET, por ejemplo. WebClient.cs :
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public Task<string> UploadStringTaskAsync(Uri address, string method, string data)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<string>(address);
// Setup the callback event handler
UploadStringCompletedEventHandler handler = null;
handler = (sender, e) => HandleCompletion(tcs, e, (args) => args.Result, handler, (webClient, completion) => webClient.UploadStringCompleted -= completion);
this.UploadStringCompleted += handler;
// Start the async operation.
try { this.UploadStringAsync(address, method, data, tcs); }
catch
{
this.UploadStringCompleted -= handler;
throw;
}
// Return the task that represents the async operation
return tcs.Task;
}
Finalmente, encontré útil también lo siguiente:
Me hacen esta pregunta todo el tiempo. La implicación es que debe haber algún hilo en algún lugar que esté bloqueando la llamada de E / S al recurso externo. Entonces, el código asincrónico libera el hilo de solicitud, pero solo a expensas de otro hilo en otra parte del sistema, ¿verdad? No, en absoluto. Para comprender por qué escalan las solicitudes asíncronas, rastrearé un ejemplo (simplificado) de una llamada de E / S asíncrona. Digamos que una solicitud necesita escribir en un archivo. El subproceso de solicitud llama al método de escritura asincrónico. WriteAsync es implementado por la Base Class Library (BCL), y utiliza puertos de finalización para su E / S asíncrona. Entonces, la llamada WriteAsync se pasa al sistema operativo como una escritura de archivo asíncrono. Luego, el sistema operativo se comunica con la pila de controladores, pasando los datos para escribir en un paquete de solicitud de E / S (IRP). Aquí es donde las cosas se ponen interesantes: Si un controlador de dispositivo no puede manejar un IRP de inmediato, debe manejarlo de forma asincrónica. Entonces, el controlador le dice al disco que comience a escribir y devuelve una respuesta "pendiente" al sistema operativo. El sistema operativo pasa esa respuesta "pendiente" al BCL, y el BCL devuelve una tarea incompleta al código de manejo de solicitudes. El código de manejo de solicitudes espera la tarea, que devuelve una tarea incompleta de ese método, etc. Finalmente, el código de manejo de solicitudes termina devolviendo una tarea incompleta a ASP.NET, y el subproceso de solicitud se libera para volver al grupo de subprocesos. El código de manejo de solicitudes espera la tarea, que devuelve una tarea incompleta de ese método, etc. Finalmente, el código de manejo de solicitudes termina devolviendo una tarea incompleta a ASP.NET, y el subproceso de solicitud se libera para volver al grupo de subprocesos. El código de manejo de solicitudes espera la tarea, que devuelve una tarea incompleta de ese método, etc. Finalmente, el código de manejo de solicitudes termina devolviendo una tarea incompleta a ASP.NET, y el subproceso de solicitud se libera para volver al grupo de subprocesos.
Introducción a Async / Await en ASP.NET
Si el objetivo es mejorar la escalabilidad (en lugar de la capacidad de respuesta), todo depende de la existencia de una E / S externa que brinde la oportunidad de hacerlo.