445 Stimmen

Unterschiede zwischen Task und Thread

In .NET gibt es zwei Klassen: Task y Thread .

  • Worin besteht der Unterschied zwischen diesen Klassen?
  • Wann ist es besser, die Thread über Task (und vice versa)?

545voto

Jon Skeet Punkte 1325502

Thread ist ein Konzept auf niedrigerer Ebene: Wenn Sie direkt einen Thread starten, müssen Sie wissen Es wird ein separater Thread sein, der nicht im Thread-Pool ausgeführt wird usw.

Task ist jedoch mehr als nur eine Abstraktion von "wo ein Code ausgeführt werden soll" - es ist wirklich nur "das Versprechen eines Ergebnisses in der Zukunft". Um nur einige Beispiele zu nennen:

  • Task.Delay benötigt keine tatsächliche CPU-Zeit; es ist wie das Einstellen eines Timers, der in der Zukunft abläuft
  • Eine Aufgabe, die von WebClient.DownloadStringTaskAsync wird lokal nicht viel CPU-Zeit beanspruchen; es stellt ein Ergebnis dar, das wahrscheinlich die meiste Zeit mit Netzwerklatenz oder Remote-Arbeit (auf dem Webserver) verbringen wird
  • Eine Aufgabe, die von Task.Run() wirklich es Sie sagen: "Ich möchte, dass Sie diesen Code separat ausführen"; der genaue Thread, in dem dieser Code ausgeführt wird, hängt von einer Reihe von Faktoren ab.

Beachten Sie, dass die Task<T> Abstraktion ist für die asynchrone Unterstützung in C# 5 von zentraler Bedeutung.

Im Allgemeinen würde ich empfehlen, dass Sie die Abstraktion auf höherer Ebene verwenden, wo immer Sie können: In modernem C#-Code sollten Sie selten explizit Ihren eigenen Thread starten müssen.

58voto

Roman Pokrovskij Punkte 8762

Normalerweise hört man Aufgabe ist ein Konzept höherer Ebene als Thread ... und das ist es, was dieser Satz bedeutet:

  1. Sie können Abort/ThreadAbortedException nicht verwenden, Sie sollten cancel event in Ihrem "Business Code" regelmäßig testen token.IsCancellationRequested Flag (vermeiden Sie auch lange oder zeitlose Verbindungen z.B. zu db, sonst werden Sie nie die Chance haben, dieses Flag zu testen). Aus dem gleichen Grund Thread.Sleep(delay) Aufruf sollte ersetzt werden durch Task.Delay(delay, token) Aufruf (Übergabe des Tokens, um die Verzögerung unterbrechen zu können).

  2. Es gibt keine Threads Suspend y Resume Methodenfunktionalität mit Aufgaben. Instanz einer Aufgabe kann nicht wiederverwendet werden entweder.

  3. Aber Sie erhalten zwei neue Werkzeuge:

    a) Fortsetzungen

    // continuation with ContinueWhenAll - execute the delegate, when ALL
    // tasks[] had been finished; other option is ContinueWhenAny
    
    Task.Factory.ContinueWhenAll( 
       tasks,
       () => {
           int answer = tasks[0].Result + tasks[1].Result;
           Console.WriteLine("The answer is {0}", answer);
       }
    );

    b) verschachtelte/untergeordnete Aufgaben

    //StartNew - starts task immediately, parent ends whith child
    var parent = Task.Factory.StartNew
    (() => {
              var child = Task.Factory.StartNew(() =>
             {
             //...
             });
          },  
          TaskCreationOptions.AttachedToParent
    );
  4. Der System-Thread ist also vollständig vor der Aufgabe verborgen, aber der Code der Aufgabe wird dennoch im konkreten System-Thread ausgeführt. System-Threads sind Ressourcen für Aufgaben und natürlich gibt es noch einen Thread-Pool unter der Haube der parallelen Ausführung von Aufgaben. Es kann verschiedene Strategien geben, wie Threads neue Aufgaben zur Ausführung erhalten. Eine weitere gemeinsam genutzte Ressource TaskScheduler kümmert sich darum. Einige Probleme, die TaskScheduler löst 1) bevorzugt die Ausführung einer Aufgabe und ihrer Verknüpfung im selben Thread, um die Umschaltkosten zu minimieren - auch bekannt als Inline-Ausführung ) 2) lieber Aufgaben in der Reihenfolge ausführen, in der sie gestartet wurden - aka PreferFairness 3) effektivere Verteilung von Aufgaben zwischen inaktiven Threads je nach "Vorkenntnis der Aufgabenaktivität" - auch bekannt als Arbeit stehlen . Wichtig: im Allgemeinen ist "async" nicht dasselbe wie "parallel". Mit den TaskScheduler-Optionen können Sie asynchrone Aufgaben so einstellen, dass sie in einem Thread synchron ausgeführt werden. Um parallele Codeausführung auszudrücken, können höhere Abstraktionen (als Tasks) verwendet werden: Parallel.ForEach , PLINQ , Dataflow .

  5. Tasks sind mit C# async/await-Funktionen integriert, auch bekannt als Versprechen Modell , z.B. dort requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName)); die Ausführung von client.RequestAsync wird den UI-Thread nicht blockieren. Wichtig: unter der Haube Clicked Der Aufruf von Delegaten ist absolut regulär (das gesamte Threading wird vom Compiler durchgeführt).

Das reicht aus, um eine Entscheidung zu treffen. Wenn Sie die Cancel-Funktionalität des Aufrufs von Legacy-APIs unterstützen müssen, die zum Hängen neigen (z.B. zeitlose Verbindung) und für diesen Fall Thread.Abort() unterstützen, oder wenn Sie Multithread-Hintergrundberechnungen erstellen und den Wechsel zwischen Threads mit Suspend/Resume optimieren wollen, d.h. die parallele Ausführung manuell verwalten wollen - bleiben Sie bei Thread. Andernfalls sollten Sie sich für Tasks entscheiden, da diese eine einfache Manipulation von Gruppen ermöglichen, in die Sprache integriert sind und Entwickler produktiver machen. Aufgabenparallele Bibliothek (TPL) .

44voto

Justin Punkte 82143

En Thread Klasse dient der Erstellung und Bearbeitung einer fil in Windows.

A Task stellt eine asynchrone Operation dar und ist Teil der Aufgabe Parallele Bibliothek , eine Reihe von APIs für die asynchrone und parallele Ausführung von Aufgaben.

In den alten Tagen (d.h. vor TPL) war es üblich, dass die Verwendung des Thread Klasse war eine der Standardmethoden, um Code im Hintergrund oder parallel auszuführen (eine bessere Alternative war oft die Verwendung einer ThreadPool ), dies war jedoch umständlich und hatte mehrere Nachteile, nicht zuletzt den Leistungs-Overhead, der durch die Erstellung eines völlig neuen Threads zur Ausführung einer Aufgabe im Hintergrund entsteht.

Heutzutage ist die Verwendung von Tasks und der TPL in 90 % der Fälle eine weitaus bessere Lösung, da sie Abstraktionen bietet, die eine weitaus effizientere Nutzung der Systemressourcen ermöglichen. Ich kann mir vorstellen, dass es ein paar Szenarien gibt, in denen man explizit die Kontrolle über den Thread haben möchte, auf dem man seinen Code ausführt, aber im Allgemeinen, wenn man etwas asynchron ausführen möchte, sollte die erste Anlaufstelle die TPL sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X