Tout d'abord, nous allons clarifier la terminologie: "asynchrone" (async
) signifie qu'il peut céder le contrôle de retour pour le thread appelant avant qu'il ne commence. Dans un async
méthode, ces "rendement" points sont await
expressions.
C'est très différent que le terme "asynchrone", comme (sig)utilisé par la documentation MSDN pour les années à dire "s'exécute sur un thread d'arrière-plan".
Pour de plus amples confondre la question, async
est très différent de "awaitable"; il y a quelques async
méthodes dont le type de retour ne sont pas awaitable, et de nombreuses méthodes de retour awaitable types qui ne sont pas async
.
Assez sur ce qu'ils ne sont pas; voici ce qu'ils sont:
- L'
async
mot-clé permet une méthode asynchrone (qui est, elle permet d' await
expressions). async
méthodes peuvent renvoyer Task
, Task<T>
, ou (si vous devez) void
.
- Tout type qui suit un certain modèle peut être awaitable. La plus courante awaitable types sont
Task
et Task<T>
.
Donc, si nous reformuler votre question "comment puis-je exécuter une opération sur un thread d'arrière-plan d'une manière qui il est awaitable", 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 un async
méthode qui peut le rendement jusqu'à son appelant au lieu de le bloquer", la réponse est de déclarer la méthode async
et l'utilisation await
pour son "rendement" des points:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Ainsi, le motif de base des choses, c'est d'avoir async
code dépendent de "awaitables" dans ses await
expressions. Ces "awaitables" peut-être d'autres async
méthodes ou tout simplement des méthodes régulières de retour awaitables. Régulièrement les méthodes retournant Task
/Task<T>
pouvez utiliser Task.Run
d'exécuter du code sur un thread d'arrière-plan, ou (plus souvent) qu'ils peuvent utiliser TaskCompletionSource<T>
ou l'un de ses raccourcis (TaskFactory.FromAsync
, Task.FromResult
, etc). Je ne pas recommander l'enchaînement d'un ensemble de méthode en Task.Run
; les méthodes synchrones doivent avoir synchrone signatures, et il devrait être laissé au consommateur qu'il doit être enveloppé 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 un async
/await
intro sur mon blog; à la fin, il est intéressant de suivi des ressources. La MSDN docs pour async
sont exceptionnellement bonnes, aussi.