J'ai la méthode:
private static void Method()
{
Console.WriteLine("Method() started");
for (var i = 0; i < 20; i++)
{
Console.WriteLine("Method() Counter = " + i);
Thread.Sleep(500);
}
Console.WriteLine("Method() finished");
}
Et je veux démarrer cette méthode dans une nouvelle tâche. Je peux commencer une nouvelle tâche comme celle-ci
var task = Task.Factory.StartNew(new Action(Method));
ou ca
var task = Task.Run(new Action(Method));
Mais y a-t-il une différence entre Task.Run()
et Task.Factory.StartNew()
. Les deux utilisent ThreadPool et démarrent Method () immédiatement après la création de l'instance de la tâche. Quand devrions-nous utiliser la première variante et la seconde?
c#
multithreading
task-parallel-library
Sergiy Lichenko
la source
la source
StartNew
par défaut les utilisationsTaskScheduler.Current
qui peuvent être le pool de threads mais également le thread d'interface utilisateur.Réponses:
La deuxième méthode,
Task.Run
a été introduite dans une version ultérieure du framework .NET (dans .NET 4.5).Cependant, la première méthode
Task.Factory.StartNew
,, vous donne la possibilité de définir beaucoup de choses utiles sur le fil que vous souhaitez créer, maisTask.Run
ne fournit pas cela.Par exemple, disons que vous souhaitez créer un fil de tâche de longue durée. Si un thread du pool de threads va être utilisé pour cette tâche, cela peut être considéré comme un abus du pool de threads.
Une chose que vous pourriez faire pour éviter cela serait d'exécuter la tâche dans un thread séparé. Un thread nouvellement créé qui serait dédié à cette tâche et serait détruit une fois votre tâche terminée. Vous ne pouvez pas y parvenir avec le
Task.Run
, alors que vous pouvez le faire avec leTask.Factory.StartNew
, comme ci-dessous:Comme il est indiqué ici :
la source
that’s exactly equivalent to
ne tient pas.tha's exactly equivalent to
ne tient pas. Merci d'avance. Ce serait bien d'expliquer en commentant votre code. Merci :)TaskScheduler.Default
. Veuillez jeter un œil ici referencesource.microsoft.com/#mscorlib/system/threading/Tasks/… .Les gens ont déjà mentionné que
Est équivalent à
Mais personne n'a mentionné ça
Est équivalent à:
Comme vous pouvez le voir, deux paramètres sont différents pour
Task.Run
etTask.Factory.StartNew
:TaskCreationOptions
-Task.Run
utiliseTaskCreationOptions.DenyChildAttach
ce qui signifie que les tâches enfants ne peuvent pas être attachées au parent, considérez ceci:Lorsque nous invoquons
parentTask.Wait()
,childTask
ne sera pas attendu, même si nous l'avons spécifiéTaskCreationOptions.AttachedToParent
, c'est parce qu'ilTaskCreationOptions.DenyChildAttach
interdit aux enfants de s'y attacher. Si vous exécutez le même code avecTask.Factory.StartNew
au lieu deTask.Run
,parentTask.Wait()
attendrachildTask
carTask.Factory.StartNew
utiliseTaskCreationOptions.None
TaskScheduler
-Task.Run
utiliseTaskScheduler.Default
ce qui signifie que le planificateur de tâches par défaut (celui qui exécute les tâches sur le pool de threads) sera toujours utilisé pour exécuter les tâches.Task.Factory.StartNew
d'autre part utiliseTaskScheduler.Current
ce qui signifie planificateur du thread actuel, cela pourrait êtreTaskScheduler.Default
mais pas toujours. En fait, lors du développementWinforms
ou desWPF
applications, il est nécessaire de mettre à jour l'interface utilisateur à partir du thread actuel, pour ce faire, les gens utilisent leTaskScheduler.FromCurrentSynchronizationContext()
planificateur de tâches, si vous créez involontairement une autre tâche de longue durée dans la tâche qui utilisait leTaskScheduler.FromCurrentSynchronizationContext()
planificateur, l'interface utilisateur sera gelée. Une explication plus détaillée de ceci peut être trouvée iciDonc, généralement, si vous n'utilisez pas de tâche enfant imbriquée et que vous voulez toujours que vos tâches soient exécutées sur le pool de threads, il est préférable de l'utiliser
Task.Run
, sauf si vous avez des scénarios plus complexes.la source
Consultez cet article de blog qui décrit la différence. En gros, faire:
C'est la même chose que de faire:
la source
Il a
Task.Run
été introduit dans la nouvelle version du framework .NET et il est recommandé .Le
Task.Factory.StartNew
a plus d'options,Task.Run
c'est un raccourci:Et par raccourci, j'entends un raccourci technique :
la source
Selon cet article de Stephen Cleary, Task.Factory.StartNew () est dangereux:
Voici les raisons réelles:
Cela signifie donc qu'il pourrait potentiellement s'exécuter sur le thread de l'interface utilisateur si une opération se termine et qu'il revient au thread de l'interface utilisateur en raison d'une continuation, comme l'explique plus en détail Stephen Cleary dans son article.
Dans mon cas, j'essayais d'exécuter des tâches en arrière-plan lors du chargement d'une grille de données pour une vue tout en affichant une animation chargée. L'animation occupée ne s'affichait pas lors de l'utilisation,
Task.Factory.StartNew()
mais l'animation s'affichait correctement lorsque je suis passé àTask.Run()
.Pour plus de détails, veuillez consulter https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html
la source
Outre les similitudes, à savoir Task.Run () étant un raccourci pour Task.Factory.StartNew (), il y a une différence minime entre leur comportement en cas de délégués sync et async.
Supposons qu'il existe deux méthodes suivantes:
Considérons maintenant le code suivant.
Ici, sync1 et sync2 sont de type Task <int>
Cependant, la différence vient dans le cas des méthodes asynchrones.
Dans ce scénario, async1 est de type Task <int>, cependant async2 est de type Task <Task <int>>
la source
Task.Run
a intégré la fonctionnalité de déballage de laUnwrap
méthode. Voici un article de blog qui explique le raisonnement derrière cette décision.Dans mon application qui appelle deux services, j'ai comparé à la fois Task.Run et Task.Factory.StartNew . J'ai trouvé que dans mon cas, les deux fonctionnent bien. Cependant, le second est plus rapide.
la source