Si vous ne vouliez pas utiliser async / await dans votre méthode, mais que vous la "décorez" de manière à pouvoir utiliser le mot-clé await de l'extérieur, 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;
}
D'ici et d' ici
Pour prendre en charge un tel paradigme avec les tâches, nous avons besoin d'un moyen de conserver la façade de la tâche et de la possibilité de faire référence à une opération asynchrone arbitraire en tant que tâche, mais de contrôler la durée de vie de cette tâche selon les règles de l'infrastructure sous-jacente qui fournit le asynchrone, et de le faire d'une manière qui ne coûte pas beaucoup. C'est le but de TaskCompletionSource.
J'ai vu est également utilisé dans la source .NET, par exemple. 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;
}
Enfin, j'ai trouvé utile aussi ce qui suit:
On me pose cette question tout le temps. L'implication est qu'il doit y avoir un thread quelque part qui bloque l'appel d'E / S à la ressource externe. Ainsi, le code asynchrone libère le thread de requête, mais uniquement au détriment d'un autre thread ailleurs dans le système, non? Non pas du tout. Pour comprendre pourquoi les demandes asynchrones évoluent, je vais tracer un exemple (simplifié) d'un appel d'E / S asynchrone. Disons qu'une requête doit écrire dans un fichier. Le thread de demande appelle la méthode d'écriture asynchrone. WriteAsync est implémenté par la bibliothèque de classes de base (BCL) et utilise des ports d'achèvement pour ses E / S asynchrones. Ainsi, l'appel WriteAsync est transmis au système d'exploitation en tant qu'écriture de fichier asynchrone. Le système d'exploitation communique ensuite avec la pile de pilotes, transmettant les données à écrire dans un paquet de demande d'E / S (IRP). C'est là que les choses deviennent intéressantes: Si un pilote de périphérique ne peut pas gérer un IRP immédiatement, il doit le gérer de manière asynchrone. Ainsi, le pilote dit au disque de commencer à écrire et renvoie une réponse «en attente» au système d'exploitation. Le système d'exploitation transmet cette réponse «en attente» à la BCL, et la BCL renvoie une tâche incomplète au code de gestion des demandes. Le code de gestion des demandes attend la tâche, qui renvoie une tâche incomplète de cette méthode et ainsi de suite. Enfin, le code de gestion des demandes finit par renvoyer une tâche incomplète à ASP.NET, et le thread de demande est libéré pour revenir au pool de threads. Le code de gestion des demandes attend la tâche, qui renvoie une tâche incomplète de cette méthode et ainsi de suite. Enfin, le code de gestion des demandes finit par renvoyer une tâche incomplète à ASP.NET, et le thread de demande est libéré pour revenir au pool de threads. Le code de gestion des demandes attend la tâche, qui renvoie une tâche incomplète de cette méthode et ainsi de suite. Enfin, le code de gestion des demandes finit par renvoyer une tâche incomplète à ASP.NET, et le thread de demande est libéré pour revenir au pool de threads.
Introduction à Async / Await sur ASP.NET
Si l'objectif est d'améliorer l'évolutivité (plutôt que la réactivité), tout repose sur l'existence d'une E / S externe qui offre la possibilité de le faire.