Ich sehe viele Leute in Blog-Posts und hier auf SO, die die Verwendung der Thread
Klasse in neueren Versionen von C # entweder vermeiden oder davon abraten (und ich meine natürlich 4.0+, mit dem Zusatz von Task
& friends). Schon vorher gab es Debatten darüber, dass die Funktionalität eines einfachen alten Threads in vielen Fällen durch die ThreadPool
Klasse ersetzt werden kann.
Auch andere spezialisierte Mechanismen machen die Thread
Klasse weniger attraktiv, wie z. B. das Timer
Ersetzen der hässlichen Thread
+ Sleep
Kombination, während wir für GUIs BackgroundWorker
usw. haben .
Dennoch Thread
scheint das Konzept für einige Leute (mich eingeschlossen) ein sehr vertrautes Konzept zu bleiben, Leute, die, wenn sie mit einer Aufgabe konfrontiert werden, die eine Art parallele Ausführung beinhaltet, direkt zur Verwendung der guten alten Thread
Klasse springen . Ich habe mich in letzter Zeit gefragt, ob es Zeit ist, meine Wege zu ändern.
Meine Frage ist also, gibt es Fälle, in denen es notwendig oder nützlich ist, ein einfaches altes Thread
Objekt anstelle eines der oben genannten Konstrukte zu verwenden?
quelle
64.5k
. Ziemlich beeindruckendAntworten:
Die Thread-Klasse kann nicht überholt werden, da es sich offensichtlich um ein Implementierungsdetail aller anderen von Ihnen erwähnten Muster handelt.
Aber das ist nicht wirklich deine Frage; Ihre Frage ist
Sicher. In genau den Fällen, in denen eines der übergeordneten Konstrukte Ihren Anforderungen nicht entspricht.
Mein Rat ist, dass Sie, wenn Sie sich in einer Situation befinden, in der vorhandene Tools mit höherer Abstraktion nicht Ihren Anforderungen entsprechen und eine Lösung mithilfe von Threads implementieren möchten , die fehlende Abstraktion identifizieren sollten , die Sie wirklich benötigen , und diese Abstraktion dann implementieren sollten Verwenden Sie Threads und verwenden Sie dann die Abstraktion .
quelle
Threads sind ein grundlegender Baustein für bestimmte Dinge (nämlich Parallelität und Asynchronität) und sollten daher nicht entfernt werden. Allerdings , für die meisten Menschen und die meisten Anwendungsfälle gibt es geeignetere Dinge zu verwenden sind , die Sie, wie Thread - Pools genannt (die parallel eine schöne Art und Weise bieten viele kleine Jobs Handling ohne durch Laichen 2000 Fäden auf einmal Überlastung der Maschine),
BackgroundWorker
( die nützliche Ereignisse für eine einzelne kurzlebige Arbeit zusammenfasst).Aber nur weil diese in vielen Fällen besser geeignet sind, da sie den Programmierer davor schützen, das Rad unnötig neu zu erfinden, dumme Fehler zu machen und dergleichen, bedeutet dies nicht, dass die Thread-Klasse veraltet ist. Es wird immer noch von den oben genannten Abstraktionen verwendet, und Sie würden es immer noch benötigen, wenn Sie eine fein abgestimmte Kontrolle über Threads benötigen, die nicht von den spezielleren Klassen abgedeckt werden.
In ähnlicher Weise
.NET
verbietet es nicht die Verwendung von Arrays, obwohlList<T>
es für viele Fälle, in denen Menschen Arrays verwenden, besser geeignet ist. Einfach, weil Sie möglicherweise immer noch Dinge erstellen möchten, die nicht von der Standardbibliothek abgedeckt werden.quelle
Task
undThread
sind verschiedene Abstraktionen. Wenn Sie einen Thread modellieren möchten, ist dieThread
Klasse immer noch die am besten geeignete Wahl. Wenn Sie beispielsweise mit dem aktuellen Thread interagieren müssen, sehe ich dafür keine besseren Typen.Wie Sie jedoch hervorheben, hat .NET mehrere dedizierte Abstraktionen hinzugefügt, die
Thread
in vielen Fällen vorzuziehen sind.quelle
Die
Thread
Klasse ist nicht veraltet, sie ist unter besonderen Umständen immer noch nützlich.Wo ich arbeite, haben wir einen 'Hintergrundprozessor' als Teil eines Content-Management-Systems geschrieben: einen Windows-Dienst, der Verzeichnisse, E-Mail-Adressen und RSS-Feeds überwacht und jedes Mal, wenn etwas Neues auftaucht, eine Aufgabe darauf ausführt - normalerweise, um das zu importieren Daten.
Versuche, den Thread-Pool dafür zu verwenden, haben nicht funktioniert: Es wird versucht, zu viel Material gleichzeitig auszuführen und die Datenträger in den Papierkorb zu werfen. Daher haben wir unser eigenes Abfrage- und Ausführungssystem implementiert, indem wir die
Thread
Klasse direkt verwendeten .quelle
Die neuen Optionen machen die direkte Verwendung und Verwaltung der (teuren) Threads weniger häufig.
Das ist eine sehr teure und relativ komplexe Art, Dinge parallel zu machen.
Beachten Sie, dass die Kosten am wichtigsten sind: Sie können keinen vollständigen Thread für kleine Aufgaben verwenden, dies wäre kontraproduktiv. Der ThreadPool bekämpft die Kosten, die Task-Klasse die Komplexität (Ausnahmen, Warten und Abbrechen).
quelle
Um die Frage zu beantworten: " Gibt es Fälle, in denen es notwendig oder nützlich ist, ein einfaches altes Thread-Objekt zu verwenden?" ", Würde ich sagen, dass ein einfacher alter Thread nützlich (aber nicht notwendig) ist, wenn Sie einen lang laufenden Prozess haben, den Sie gewonnen haben. nie mit einem anderen Thread interagieren.
Wenn Sie beispielsweise eine Anwendung schreiben, die Nachrichten aus einer Nachrichtenwarteschlange abonniert, und Ihre Anwendung mehr als nur diese Nachrichten verarbeitet, ist es hilfreich, einen Thread zu verwenden, da dies der Thread ist in sich geschlossen (dh Sie warten nicht darauf, dass es erledigt wird), und es ist nicht von kurzer Dauer. Die Verwendung der ThreadPool-Klasse dient eher dazu, eine Reihe von kurzlebigen Arbeitselementen in die Warteschlange zu stellen und der ThreadPool-Klasse die effiziente Verarbeitung jedes einzelnen zu ermöglichen, sobald ein neuer Thread verfügbar ist. Aufgaben können verwendet werden, wenn Sie Thread direkt verwenden würden, aber im obigen Szenario glaube ich nicht, dass sie Ihnen viel kosten würden. Sie helfen Ihnen dabei, einfacher mit dem Thread zu interagieren (was im obigen Szenario nicht der Fall ist).
quelle
System.IO.Threading.Thread
.Wahrscheinlich nicht die Antwort, die Sie erwartet hatten, aber ich verwende Thread die ganze Zeit beim Codieren gegen .NET Micro Framework. MF ist ziemlich reduziert und enthält keine Abstraktionen auf höherer Ebene. Die Thread-Klasse ist sehr flexibel, wenn Sie das letzte Stück Leistung aus einer Low-MHz-CPU herausholen möchten.
quelle
Sie können die Thread-Klasse mit ADO.NET vergleichen. Es ist nicht das empfohlene Tool, um die Arbeit zu erledigen, aber es ist nicht veraltet. Andere Tools bauen darauf auf, um die Arbeit zu erleichtern.
Es ist nicht falsch, die Thread-Klasse über andere Dinge zu verwenden, insbesondere wenn diese Dinge keine Funktionalität bieten, die Sie benötigen.
quelle
Es ist nicht definitiv veraltet.
Das Problem bei Multithread-Apps besteht darin, dass es sehr schwierig ist, sie richtig zu machen (oft ist unbestimmtes Verhalten, Eingabe, Ausgabe und auch der interne Status wichtig). Daher sollte ein Programmierer so viel Arbeit wie möglich auf Framework / Tools übertragen. Abstrakt es weg. Aber der Todfeind der Abstraktion ist die Leistung.
Ich würde mich nur für Threads und Sperren entscheiden, wenn es ernsthafte Leistungsprobleme und Hochleistungsziele gibt.
quelle
Ich habe immer die Thread-Klasse verwendet, wenn ich die Anzahl der Threads, die ich hochgefahren habe, zählen und kontrollieren muss. Mir ist klar, dass ich den Threadpool verwenden könnte, um alle meine herausragenden Arbeiten zu speichern, aber ich habe nie einen guten Weg gefunden, um zu verfolgen, wie viel Arbeit gerade erledigt wird oder wie der Status ist.
Stattdessen erstelle ich eine Sammlung und platziere die Threads in ihnen, nachdem ich sie hochgefahren habe. Das allerletzte, was ein Thread tut, ist, sich selbst aus der Sammlung zu entfernen. Auf diese Weise kann ich immer feststellen, wie viele Threads ausgeführt werden, und ich kann die Sammlung verwenden, um jeden zu fragen, was er tut. Wenn es einen Fall gibt, in dem ich sie alle töten muss, müssen Sie normalerweise eine Art "Abbruch" -Flag in Ihrer Anwendung setzen. Warten Sie, bis jeder Thread dies für sich bemerkt und sich selbst beendet - in meinem Fall ich kann durch die Sammlung gehen und nacheinander einen Thread.Abort für jeden ausgeben.
In diesem Fall habe ich keinen besseren Weg gefunden, als direkt mit der Thread-Klasse zu arbeiten. Wie Eric Lippert erwähnte, handelt es sich bei den anderen nur um Abstraktionen auf höherer Ebene, und es ist angebracht, mit den Klassen auf niedrigerer Ebene zu arbeiten, wenn die verfügbaren Implementierungen auf höherer Ebene nicht Ihren Anforderungen entsprechen. So wie Sie manchmal Win32-API-Aufrufe ausführen müssen, wenn .NET nicht genau Ihren Anforderungen entspricht, wird es immer Fälle geben, in denen die Thread-Klasse trotz der jüngsten "Fortschritte" die beste Wahl ist.
quelle