On m'a donc dit récemment que la façon dont j'utilisais mon .ContinueWith for Tasks n'était pas la bonne façon de les utiliser. Je n'ai pas encore trouvé de preuves de cela sur Internet, alors je vais vous demander les gars et voir quelle est la réponse. Voici un exemple de la façon dont j'utilise .ContinueWith:
public Task DoSomething()
{
return Task.Factory.StartNew(() =>
{
Console.WriteLine("Step 1");
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("Step 2");
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("Step 3");
});
}
Maintenant, je sais que c'est un exemple simple et qu'il fonctionnera très rapidement, mais supposons simplement que chaque tâche effectue une opération plus longue. Donc, on m'a dit que dans le .ContinueWith, vous devez dire prevTask.Wait (); sinon, vous pourriez travailler avant la fin de la tâche précédente. Est-ce que c'est possible? J'ai supposé que ma deuxième et troisième tâche ne s'exécuteraient qu'une fois leur tâche précédente terminée.
Ce qu'on m'a dit comment écrire le code:
public Task DoSomething()
{
return Task.Factory.StartNew(() =>
{
Console.WriteLine("Step 1");
})
.ContinueWith((prevTask) =>
{
prevTask.Wait();
Console.WriteLine("Step 2");
})
.ContinueWith((prevTask) =>
{
prevTask.Wait();
Console.WriteLine("Step 3");
});
}
la source
Réponses:
Ehhh ... Je pense que certaines des réponses actuelles manquent quelque chose: que se passe-t-il avec des exceptions?
La seule raison pour laquelle vous appelleriez
Wait
une continuation serait d'observer une exception potentielle à l'antécédent dans la continuation elle-même. La même observation se produirait si vous y accédezResult
dans le cas d'unTask<T>
et également si vous avez accédé manuellement à laException
propriété. Franchement, je n'appellerais pasWait
ou n'y accéderais pasResult
parce que s'il y a une exception, vous paierez le prix de la relancer, ce qui est des frais généraux inutiles. Au lieu de cela, vous pouvez simplement cocher laIsFaulted
propriété de l'antécédentTask
. Vous pouvez également créer des flux de travail fourchus en enchaînant sur plusieurs continuations frères qui ne se déclenchent qu'en cas de succès ou d'échec avecTaskContinuationOptions.OnlyOnRanToCompletion
etTaskContinuationOptions.OnlyOnFaulted
.Désormais, il n'est pas nécessaire d'observer l'exception de l'antécédent dans la suite, mais vous ne voudrez peut-être pas que votre flux de travail avance si, par exemple, «l'étape 1» a échoué. Dans ce cas: la spécification
TaskContinuationOptions.NotOnFaulted
de vosContinueWith
appels empêcherait la logique de continuation de se déclencher même.Gardez à l'esprit que, si vos propres continuations ne respectent pas l'exception, la personne qui attend que ce flux de travail global se termine sera celle qui l'observera. Soit ils sont
Wait
enTask
amont, soit ils se sont lancés sur leur propre continuation pour savoir quand elle est terminée. Si c'est ce dernier, leur poursuite devrait utiliser la logique d'observation susmentionnée.la source
TaskContinuationOptions
Vous l'utilisez correctement.
Source: Méthode Task.ContinueWith (Action en tant que MSDN)
Devoir appeler
prevTask.Wait()
à chaqueTask.ContinueWith
invocation semble être une façon étrange de répéter une logique inutile - c'est-à-dire faire quelque chose pour être "super sûr" parce que vous ne comprenez pas vraiment ce que fait un certain morceau de code. Comme vérifier un null juste pour lancer unArgumentNullException
là où il aurait été jeté de toute façon.Donc, non, celui qui vous a dit cela est faux et ne comprend probablement pas pourquoi
Task.ContinueWith
existe.la source
Qui t'as dit ça?
Citant MSDN :
De plus, quel serait le but de Continuer avec s'il n'attendait pas que la tâche précédente soit terminée?
Vous pouvez même le tester par vous-même:
la source
Depuis le MSDN sur
Task.Continuewith
Je pense que la manière dont vous vous attendez à ce que cela fonctionne dans le premier exemple est la bonne manière.
la source
Vous pouvez également envisager d'utiliser Task.Run au lieu de Task.Factory.StartNew.
Le billet de blog de Stephen Cleary et l'article de Stephen Toub auquel il fait référence expliquent les différences. Il y a aussi une discussion dans cette réponse .
la source
En accédant,
Task.Result
vous faites en fait une logique similaire à celletask.wait
la source
Je vais répéter ce que beaucoup ont déjà dit,
prevTask.Wait()
est inutile .Pour plus d'exemples, vous pouvez aller à Chaining Tasks using Continuation Tasks , encore un autre lien de Microsoft avec de bons exemples.
la source