Async-attendent Tâche.Run vs HttpClient.GetAsync
Je suis novice en c# 5 asynchrone fonctionnalité.
J'essaie de comprendre la différence entre ces deux implémentations:
Mise en œuvre 1:
private void Start()
{
foreach(var url in urls)
{
ParseHtml(url);
}
}
private async void ParseHtml(string url)
{
var query = BuildQuery(url); //BuildQuery is some helper method
var html = await DownloadHtml(query);
//...
MyType parsedItem = ParseHtml(html);
SaveTypeToDB(parsedItem);
}
private async Task<string> DownloadHtml(string query)
{
using (var client = new HttpClient())
try
{
var response = await client.GetAsync(query);
return (await response.Content.ReadAsAsync<string>());
}
catch (Exception ex)
{
Logger.Error(msg, ex);
return null;
}
}
De mise en œuvre de 2:
private void DoLoop()
{
foreach(var url in urls)
{
Start(url);
}
}
private async void Start(url)
{
await Task.Run( () => ParseHtml(url)) ;
}
private void ParseHtml(string url)
{
var query = BuildQuery(url); //BuildQuery is some helper method
var html = DownloadHtml(query);
//...
MyType parsedItem = ParseHtml(html);
SaveTypeToDB(parsedItem);
}
private string DownloadHtml(string query)
{
using (var client = new WebClient())
{
try
{
return client.DownloadString(query);
}
catch (Exception ex)
{
Logger.Error(msg, ex);
return null;
}
}
}
Je préfère utiliser la deuxième mise en œuvre, car il aura besoin de moins "asynchrone" signatures sur les méthodes dans mon code. J'essaie de comprendre quel est l'avantage de l'utilisation de la classe HttpClient vs à l'aide d'une nouvelle Tâche et en attendant il à la place?
Quelle est la différence entre les deux implémentations?
'async' signatures
- ne se soucient d'eux. "async" est juste un "marqueur" pour rester compatible avec l'ancien code. En pré-5.0 vous pourriez avoir des variables/fonctions avec le nom "attendent". Mais depuis les anciennes méthodes n'ont pas le "async" mot-clé, le code sera toujours compilé (w/o des changements) avec C# 5.0.
OriginalL'auteur vondip | 2012-11-23
Vous devez vous connecter pour publier un commentaire.
Qui sonne comme un très étrange justification. Vous essayez d'exécuter fondamentalement "un peu en mode asynchrone" - alors, pourquoi ne pas le dire clairement?
Absolument. La deuxième mise en œuvre de relier un fil tout en
WebClient.DownloadString
blocs, en attente de la demande est complète. La première version ne dispose pas de threads bloqués - elle repose sur une poursuite à feu lors de la demande de finitions.En outre, pensez à votre
Logger.Error
appel. Dans la version asynchrone, qui continuera de s'exécuter dans le contexte de l'original du code appelant. Donc, si cela est, disons, un Windows Forms de l'INTERFACE utilisateur, vous serez toujours sur le thread d'INTERFACE utilisateur, et vous pouvez accéder à des éléments de l'INTERFACE utilisateur, etc. Dans la deuxième version, vous serez exécuté dans un thread du pool, et auraient besoin de maréchal de retour vers le thread d'INTERFACE utilisateur pour mettre à jour l'INTERFACE utilisateur.Noter que votre
async void
méthode presque certainement ne devrait pas êtreasync void
. Vous devez seulement faire uneasync
de retour de méthodevoid
par souci de conformité avec le gestionnaire d'événement de signatures. Dans tous les autres cas, le retourTask
- de cette façon, le visiteur peut voir lorsque votre tâche est terminée, gérer les exceptions etc.Notez également que vous n'avez pas besoin d'utiliser
HttpClient
pour l'asynchronie - vous pouvez utiliserWebClient.DownloadStringTaskAsync
au lieu de cela, de sorte que votre final de la méthode pourrait devenir:Je ne comprends pas ce que tu veux dire, j'en ai peur. Éventuellement demander que, dans plus de détail comme une question distincte?
OriginalL'auteur Jon Skeet
Pour les applications serveur,
async
consiste à réduire au minimum le nombre de threads bloqués vous avez: l'augmentation de l'efficacité du pool de threads et permettant peut-être de votre programme à l'échelle de plusieurs utilisateurs.Pour les applications client où vous avez peu de chances de se préoccuper du nombre de thread,
async
fournit un moyen relativement simple de garder votre INTERFACE utilisateur de l'exécution de liquide lorsque vous effectuez I/O.Il est très différent de
Task.Run
sous le capot.OriginalL'auteur Cory Nelson
Vous ne bénéficieront de async traitement si votre thread appelant a quelque chose d'utile à faire, comme de garder l'INTERFACE utilisateur réactive. Si votre thread appelant commence seulement à une tâche et ne fait rien mais attendre jusqu'à ce que la tâche est terminée, votre processus de s'exécuter plus lentement.
Votre deuxième implémentations commence une tâche, mais vous attendez la fin de la sans rien faire d'autre. De cette façon, vous ne bénéficiez pas.
Vous n'avez pas de décrire votre environnement, mais si vous avez une INTERFACE utilisateur qui doit garder réactif, puis la mise en œuvre de la méthode 1 est ok, sauf que votre Start() n'est pas déclaré async et n'attend pas:
Vous pouvez appeler à partir d'un gestionnaire d'événement comme suit:
Remarque: le ParseHtml a est précédé par les attendent. La prochaine html sera analysé après la précédente parse est fini. Cependant, parce que l'analyse est asynchrone, le thread appelant (le thread d'INTERFACE utilisateur?) sera en mesure de faire d'autres choses comme de répondre à la saisie de l'utilisateur.
Toutefois, si votre parseHTML fonction est capable d'exécuter simultanément le code suivant serait préférable, et probablement plus rapide:
<TResult
>OriginalL'auteur Harald Coppoolse