Tout d'abord, clarifions un peu la terminologie: "asynchrone" ( async
) signifie qu'il peut redonner le contrôle au thread appelant avant qu'il ne démarre. Dans une async
méthode, ces points de "rendement" sont des await
expressions.
Ceci est très différent du terme "asynchrone", car (mis) utilisé par la documentation MSDN pendant des années pour signifier "s'exécute sur un thread d'arrière-plan".
Pour confondre encore la question, async
est très différent de "attendable"; il existe des async
méthodes dont les types de retour ne sont pas attendus, et de nombreuses méthodes qui renvoient des types attendus qui ne le sont pas async
.
Assez de ce qu'ils ne sont pas ; voici ce qu'ils sont :
- Le
async
mot-clé autorise une méthode asynchrone (c'est-à-dire qu'il autorise les await
expressions). async
méthodes peuvent revenir Task
, Task<T>
ou (si vous devez) void
.
- Tout type qui suit un certain modèle peut être attendu. Les types attendus les plus courants sont
Task
et Task<T>
.
Donc, si nous reformulons votre question en "comment puis-je exécuter une opération sur un thread d'arrière-plan d'une manière qui soit attendue", la réponse est d'utiliser Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
(Mais ce modèle est une mauvaise approche; voir ci-dessous).
Mais si votre question est "comment puis-je créer une async
méthode qui peut renvoyer à son appelant au lieu de bloquer", la réponse est de déclarer la méthode async
et de l'utiliser await
pour ses points "donnant":
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Ainsi, le modèle de base des choses est de faire async
dépendre le code des "attendables" dans ses await
expressions. Ces "attendables" peuvent être d'autres async
méthodes ou simplement des méthodes régulières renvoyant des attentes. Méthodes régulières de retour Task
/ Task<T>
peuvent utiliser Task.Run
pour exécuter du code sur un thread d'arrière - plan, ou (plus souvent) , ils peuvent utiliser TaskCompletionSource<T>
ou l' un de ses raccourcis ( TaskFactory.FromAsync
, Task.FromResult
, etc.). Je ne recommande pas d' envelopper une méthode entière dans Task.Run
; les méthodes synchrones doivent avoir des signatures synchrones, et il convient de laisser au consommateur le soin de les inclure dans un Task.Run
:
private int DoWork()
{
return 1 + 2;
}
private void MoreSynchronousProcessing()
{
// Execute it directly (synchronously), since we are also a synchronous method.
var result = DoWork();
...
}
private async Task DoVariousThingsFromTheUIThreadAsync()
{
// I have a bunch of async work to do, and I am executed on the UI thread.
var result = await Task.Run(() => DoWork());
...
}
J'ai une async
/ await
intro sur mon blog; à la fin, il y a de bonnes ressources de suivi. Les documents MSDN pour async
sont également exceptionnellement bons.