[C#] Was ist der Unterschied zwischen Task.Run () und Task.Factory.StartNew ()


Answers

Siehe diesen Blogartikel , der den Unterschied beschreibt. Grundsätzlich tun:

Task.Run(A)

Ist das gleiche wie:

Task.Factory.StartNew(A, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);   
Question

Ich habe Methode:

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");
}

Und ich möchte diese Methode in einer neuen Aufgabe starten. Ich kann so eine neue Aufgabe beginnen

var task = Task.Factory.StartNew(new Action(Method));

oder dieses

var task = Task.Run(new Action(Method));

Aber gibt es einen Unterschied zwischen Task.Run() und Task.Factory.StartNew() . Beide verwenden ThreadPool und starten Method () sofort nach dem Erstellen der Instanz der Aufgabe. Wann sollten wir die erste Variante verwenden und wann die zweite?




Nach diesem Post von Stephen Cleary ist Task.Factory.StartNew () gefährlich:

Ich sehe eine Menge Code in Blogs und in SO-Fragen, die Task.Factory.StartNew verwenden, um die Arbeit an einem Hintergrund-Thread hochzufahren. Stephen Toub hat einen ausgezeichneten Blog-Artikel, der erklärt, warum Task.Run besser ist als Task.Factory.StartNew, aber ich denke, viele Leute haben es einfach nicht gelesen (oder verstehen es nicht). Also, ich habe die gleichen Argumente genommen, eine kraftvollere Sprache hinzugefügt, und wir werden sehen, wie das geht. :) StartNew bietet viel mehr Optionen als Task.Run, aber es ist ziemlich gefährlich, wie wir sehen werden. Sie sollten Task.Run gegenüber Task.Factory.StartNew im asynchronen Code bevorzugen.

Hier sind die tatsächlichen Gründe:

  1. Versteht keine asynchronen Delegierten. Dies ist tatsächlich das gleiche wie Punkt 1 in den Gründen, warum Sie StartNew verwenden möchten. Das Problem ist, dass wenn Sie einen asynchronen Delegaten an StartNew übergeben, ist es natürlich anzunehmen, dass die zurückgegebene Aufgabe diesen Delegaten darstellt. Da StartNew jedoch asynchrone Delegaten nicht versteht, stellt diese Aufgabe nur den Anfang dieses Delegaten dar. Dies ist eine der ersten Fallstricke, auf die Programmierer stoßen, wenn sie StartNew im asynchronen Code verwenden.
  2. Confusing default scheduler. OK, Frage Zeit: Im folgenden Code, in welchem ​​Thread läuft die Methode "A"?
Task.Factory.StartNew(A);

private static void A() { }

Nun, du weißt, dass es eine Trickfrage ist, wie? Wenn Sie "einen Thread-Pool-Thread" beantwortet haben, tut es mir leid, aber das ist nicht korrekt. "A" wird auf dem laufen, was TaskScheduler gerade ausführt!

Das bedeutet, dass es möglicherweise auf dem Benutzeroberflächenthread ausgeführt werden kann, wenn eine Operation abgeschlossen wird, und es aufgrund einer Fortsetzung, die von Stephen Cleary ausführlicher in seinem Beitrag erläutert wird, zurück zum Marshall-Thread migriert.

In meinem Fall habe ich versucht, Aufgaben im Hintergrund auszuführen, wenn ich ein Datagrid für eine Ansicht lade, während gleichzeitig eine ausgelastete Animation angezeigt wird. Die ausgelastete Animation wurde nicht angezeigt, wenn Task.Factory.StartNew () verwendet wurde, aber die Animation wurde ordnungsgemäß angezeigt, als ich zu Task.Run () wechselte.

Einzelheiten finden Sie unter https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html






Links