Se você não quis usar async / waitit dentro do seu método, mas ainda o "decorou" para poder usar a palavra-chave wait de fora, 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;
}
Daqui e aqui
Para suportar esse paradigma com as Tarefas, precisamos de uma maneira de manter a fachada da Tarefa e a capacidade de nos referir a uma operação assíncrona arbitrária como uma Tarefa, mas controlar o tempo de vida dessa Tarefa de acordo com as regras da infraestrutura subjacente que fornece o assincronia e fazê-lo de uma maneira que não custe significativamente. Esse é o objetivo do TaskCompletionSource.
Eu vi também é usado na fonte .NET, por exemplo. 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, achei útil também o seguinte:
Eu recebo essa pergunta o tempo todo. A implicação é que deve haver algum encadeamento em algum lugar que esteja bloqueando a chamada de E / S para o recurso externo. Então, o código assíncrono libera o encadeamento de solicitação, mas apenas às custas de outro encadeamento em outro local do sistema, certo? Não, não mesmo. Para entender por que as solicitações assíncronas são dimensionadas, traçarei um exemplo (simplificado) de uma chamada de E / S assíncrona. Digamos que uma solicitação precise gravar em um arquivo. O encadeamento de solicitação chama o método de gravação assíncrono. O WriteAsync é implementado pela Base Class Library (BCL) e usa portas de conclusão para sua E / S assíncrona. Portanto, a chamada WriteAsync é transmitida ao sistema operacional como uma gravação assíncrona de arquivo. O sistema operacional se comunica com a pilha do driver, passando os dados para gravar em um pacote de solicitação de E / S (IRP). É onde as coisas começam a ficar interessantes: Se um driver de dispositivo não puder lidar com um IRP imediatamente, ele deverá ser tratado de forma assíncrona. Portanto, o driver diz ao disco para começar a gravar e retorna uma resposta "pendente" para o sistema operacional. O SO passa essa resposta "pendente" para a BCL, e a BCL retorna uma tarefa incompleta ao código de tratamento de solicitações. O código de tratamento de solicitações aguarda a tarefa, que retorna uma tarefa incompleta desse método e assim por diante. Por fim, o código de tratamento de solicitações acaba retornando uma tarefa incompleta ao ASP.NET e o encadeamento de solicitação é liberado para retornar ao pool de encadeamentos. O código de tratamento de solicitações aguarda a tarefa, que retorna uma tarefa incompleta desse método e assim por diante. Por fim, o código de tratamento de solicitações acaba retornando uma tarefa incompleta ao ASP.NET e o encadeamento de solicitação é liberado para retornar ao pool de encadeamentos. O código de tratamento de solicitações aguarda a tarefa, que retorna uma tarefa incompleta desse método e assim por diante. Por fim, o código de tratamento de solicitações acaba retornando uma tarefa incompleta ao ASP.NET e o encadeamento de solicitação é liberado para retornar ao pool de encadeamentos.
Introdução ao Async / Await no ASP.NET
Se o objetivo é melhorar a escalabilidade (em vez de capacidade de resposta), tudo depende da existência de uma E / S externa que forneça a oportunidade de fazer isso.