Frage

Wann sollte ich nicht den ThreadPool in .Net verwenden?

Es scheint, dass die beste Option die Verwendung eines ThreadPools ist. Warum ist dies dann nicht die einzige Option?

Welche Erfahrungen haben Sie diesbezüglich gemacht?

War es hilfreich?

Lösung

Der einzige Grund, warum ich das nicht verwenden würde ThreadPool für billiges Multithreading ist, wenn ich muss ...

  1. mit der laufenden Methode interagieren (z. B. um sie zu beenden)
  2. Führen Sie Code auf einem aus STA-Thread (das ist mir passiert)
  3. Halten Sie den Thread am Leben, nachdem meine Bewerbung gestorben ist (ThreadPool Threads sind Hintergrundthreads)
  4. für den Fall, dass ich die Priorität des Threads ändern muss.Wir können die Priorität von Threads im ThreadPool nicht ändern, was standardmäßig auf „Normal“ steht.

P.S.: Der MSDN-Artikel „Der verwaltete Thread-Pool“ enthält einen Abschnitt mit dem Titel: „Wann man keine Thread-Pool-Threads verwenden sollte“, mit einer sehr ähnlichen, aber etwas vollständigeren Liste möglicher Gründe für die Nichtverwendung des Thread-Pools.

Es gibt viele Gründe, warum Sie das überspringen müssen ThreadPool, aber wenn Sie sie nicht kennen, dann die ThreadPool sollte gut genug für dich sein.

Alternativ schauen Sie sich das Neue an Paralleles Erweiterungs-Framework, das einige nette Dinge enthält, die möglicherweise Ihren Anforderungen entsprechen, ohne dass Sie das verwenden müssen ThreadPool.

Andere Tipps

@Eric, ich muss Dean zustimmen.Threads sind teuer.Sie können nicht davon ausgehen, dass Ihr Programm das einzige ist, das ausgeführt wird.Wenn alle ressourcengierig sind, vervielfacht sich das Problem.

Ich bevorzuge es, meine Threads manuell zu erstellen und sie selbst zu steuern.Dadurch bleibt der Code sehr leicht verständlich.

Das ist in Ordnung, wenn es angemessen ist.Wenn Sie jedoch eine Reihe von Arbeitsthreads benötigen, müssen Sie Ihren Code lediglich komplizierter gestalten.Jetzt müssen Sie Code schreiben, um sie zu verwalten.Wenn Sie nur einen Thread-Pool verwenden, erhalten Sie die gesamte Thread-Verwaltung kostenlos.Und der von der Sprache bereitgestellte Thread-Pool ist höchstwahrscheinlich robuster, effizienter und weniger fehlerhaft als alles, was Sie selbst erstellen.

Thread t = new Thread(new ThreadStart(DoSomething));  
t.Start();  
t.Join();  

Ich hoffe, dass Sie normalerweise etwas zusätzlichen Code dazwischen haben Start() Und Join().Andernfalls ist der zusätzliche Thread nutzlos und Sie verschwenden ohne Grund Ressourcen.

Die Leute haben viel zu große Angst vor den Ressourcen, die Threads verbrauchen.Ich habe noch nie erlebt, dass das Erstellen und Starten eines Threads länger als eine Millisekunde dauerte.Es gibt keine feste Grenze für die Anzahl der Threads, die Sie erstellen können.Die RAM-Nutzung ist minimal.Sobald Sie ein paar hundert Threads haben, wird die CPU aufgrund von Kontextwechseln zu einem Problem, sodass Sie an diesem Punkt vielleicht Ihr Design ausgefallener gestalten möchten.

Eine Millisekunde ist eine lang Zeit auf moderner Hardware.Das sind 3 Millionen Zyklen auf einer 3-GHz-Maschine.Und noch einmal: Du bist nicht der Einzige, der Threads erstellt.Ihre Threads konkurrieren mit den Threads aller anderen Programme um die CPU.Wenn Sie nicht ganz zu viele Threads verwenden, wie auch ein anderes Programm, dann haben Sie insgesamt zu viele Threads verwendet.

Im Ernst, machen Sie das Leben nicht komplexer als es sein muss.Verwenden Sie den Thread-Pool nicht, es sei denn, Sie benötigen etwas ganz Spezielles, das er bietet.

In der Tat.Machen Sie das Leben nicht komplexer.Wenn Ihr Programm mehrere Arbeitsthreads benötigt, erfinden Sie das Rad nicht neu.Verwenden Sie den Thread-Pool.Deshalb ist es da.Würden Sie Ihre eigene String-Klasse erstellen?

Thread-Pools sind immer dann sinnvoll, wenn Sie das Konzept von Arbeitsthreads haben.Immer wenn Sie die Verarbeitung problemlos in kleinere Jobs unterteilen können, die jeweils unabhängig verarbeitet werden können, sind Arbeitsthreads (und damit ein Thread-Pool) sinnvoll.

Thread-Pools sind nicht sinnvoll, wenn Sie Threads benötigen, die völlig unterschiedliche und voneinander unabhängige Aktionen ausführen, die nicht als „Jobs“ betrachtet werden können.z. B. ein Thread für die GUI-Ereignisbehandlung, ein anderer für die Backend-Verarbeitung.Thread-Pools machen auch keinen Sinn, wenn die Verarbeitung eine Pipeline bildet.

Wenn Sie Threads haben, die einen Job starten, verarbeiten und beenden, ist ein Thread-Pool wahrscheinlich die richtige Lösung.Andernfalls wird der Thread-Pool nicht wirklich helfen.

Zur Antwort von streitsüchtig möchte ich hinzufügen, dass es am besten ist, keinen ThreadPool-Thread zu verwenden, wenn Sie garantieren müssen, dass Ihr Thread sofort mit der Arbeit beginnt.Die maximale Anzahl laufender Thread-Pool-Threads ist pro Anwendungsdomäne begrenzt, sodass Ihre Arbeit möglicherweise warten muss, wenn alle ausgelastet sind.Es heißt schließlich „Benutzerarbeitselement in die Warteschlange stellen“.

Zwei Vorbehalte natürlich:

  1. Sie können die maximale Anzahl von Thread-Pool-Threads im Code zur Laufzeit ändern, sodass nichts Sie daran hindert, die aktuelle Anzahl mit der maximalen Anzahl zu vergleichen und die maximale Anzahl bei Bedarf zu erhöhen.
  2. Das Aufmachen eines neuen Threads ist mit einer Zeitstrafe verbunden – ob es sich für Sie lohnt, den Schlag in Kauf zu nehmen, hängt von Ihren Umständen ab.

Ich spreche nicht als jemand mit nur theoretischen Wissen hier.Ich schreibe und pflege Hochvolumenanwendungen, die Multithreading stark nutzen, und finde den Thread -Pool im Allgemeinen nicht die richtige Antwort.

Ah, Argument der Autorität – aber halten Sie immer Ausschau nach Leuten, die möglicherweise zum Windows-Kernel-Team gehören.

Keiner von uns bestritt die Tatsache, dass der .NET ThreadPool möglicherweise nicht das Richtige ist, wenn Sie bestimmte Anforderungen haben.Was wir dagegen haben, ist die Bagatellisierung der Kosten für die Maschine, die mit der Erstellung eines Threads verbunden sind.

Der erhebliche Aufwand für die Erstellung eines Threads ist die Daseinsberechtigung des ThreadPools überhaupt.Ich möchte nicht, dass meine Maschinen mit Code gefüllt werden, der von Leuten geschrieben wurde, die über die Kosten für die Erstellung eines Threads falsch informiert sind und beispielsweise nicht wissen, dass dadurch in jeder einzelnen DLL eine Methode aufgerufen wird an den Prozess angehängt (von denen einige von Dritten erstellt werden) und die möglicherweise eine Menge Code aufheizen, der überhaupt nicht im RAM und mit ziemlicher Sicherheit auch nicht in L1 sein muss.

Die Form der Speicherhierarchie in einer modernen Maschine bedeutet, dass die „Ablenkung“ einer CPU das Schlimmste ist, was man tun kann, und jeder, der sich um sein Handwerk kümmert, sollte hart daran arbeiten, dies zu vermeiden.

Wenn Sie einen Vorgang ausführen, der viel Zeit in Anspruch nehmen wird, oder vielleicht einen kontinuierlichen Hintergrundthread.Ich denke, Sie könnten die Anzahl der im Pool verfügbaren Threads jederzeit erhöhen, aber es würde wenig Sinn machen, die Verwaltungskosten eines Threads zu tragen, der niemals an den Pool zurückgegeben wird.

MSDN hat hier eine Liste mit einigen Gründen:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

Es gibt mehrere Szenarien, in denen es angemessen ist, Ihre eigenen Threads zu erstellen und zu verwalten, anstatt Thread -Pool -Threads zu verwenden:

  • Sie benötigen einen Vordergrund-Thread.
  • Sie benötigen einen Thread, der eine bestimmte Priorität hat.
  • Sie haben Aufgaben, die dazu führen, dass der Thread für längere Zeit blockiert.Der Gewindepool hat eine maximale Anzahl von Fäden, sodass eine große Anzahl blockierter Gewindepool -Gewinde möglicherweise verhindern, dass die Aufgaben starten.
  • Sie müssen Threads in einem Single-Thread-Apartment platzieren.Alle ThreadPool-Threads befinden sich im Multithread-Apartment.
  • Sie benötigen eine stabile Identität, die mit dem Thread verknüpft ist, oder Sie müssen einen Thread einer Aufgabe zuweisen.

Threadpool-Threads eignen sich für Aufgaben, die beide der folgenden Kriterien erfüllen:

  1. Die Aufgabe muss nicht viel Zeit damit verbringen, darauf zu warten, dass etwas passiert
  2. Alles, was darauf wartet, dass die Aufgabe abgeschlossen wird, wird wahrscheinlich auch darauf warten, dass viele Aufgaben abgeschlossen werden, daher wird seine Planungspriorität wahrscheinlich keine großen Auswirkungen auf die Dinge haben.

Durch die Verwendung eines Threadpool-Threads anstelle der Erstellung eines neuen Threads wird eine erhebliche, aber begrenzte Zeitersparnis erzielt.Wenn diese Zeit im Vergleich zur Zeit, die zum Ausführen einer Aufgabe benötigt wird, erheblich ist, ist wahrscheinlich eine Threadpool-Aufgabe geeignet.Je länger jedoch die Ausführung einer Aufgabe dauert, desto geringer ist der Nutzen der Verwendung des Threadpools und desto größer ist die Wahrscheinlichkeit, dass die Aufgabe die Effizienz des Threadpools beeinträchtigt.

@Eric

@Derek, ich bin mit dem Szenario, das Sie als Beispiel verwenden, nicht ganz einverstanden.Wenn Sie nicht genau wissen, was auf Ihrem Computer läuft und wie viele Threads, Handles, CPU-Zeit, RAM usw. insgesamt Ihre App unter einer bestimmten Auslastung verwenden wird, sind Sie in Schwierigkeiten.

Sind Sie der einzige Zielkunde für die von Ihnen geschriebenen Programme?Wenn nicht, können Sie sich bei den meisten davon nicht sicher sein.Wenn Sie ein Programm schreiben, haben Sie im Allgemeinen keine Ahnung, ob es effektiv alleine ausgeführt werden kann oder ob es auf einem Webserver läuft, der von einem DDOS-Angriff getroffen wird.Sie können nicht wissen, wie viel CPU-Zeit Sie haben werden.

Unter der Annahme, dass sich das Verhalten Ihres Programms aufgrund von Eingaben ändert, wissen Sie selten genau, wie viel Speicher oder CPU-Zeit Ihr Programm verbrauchen wird.Sicherlich sollten Sie eine ziemlich gute Vorstellung davon haben, wie sich Ihr Programm verhalten wird, aber die meisten Programme werden nie analysiert, um genau zu bestimmen, wie viel Speicher, wie viele Handles usw.verwendet werden, da eine vollständige Analyse teuer ist.Wenn Sie keine Echtzeitsoftware schreiben, lohnt sich der Aufwand nicht.

Im Allgemeinen ist die Behauptung, genau zu wissen, wie sich Ihr Programm verhält, weit hergeholt und die Behauptung, alles über die Maschine zu wissen, wirkt lächerlich.

Und ganz ehrlich, wenn Sie nicht genau wissen, welche Methode Sie verwenden sollten:Manuelle Threads, Thread-Pool, Delegaten und wie Sie diese implementieren, um genau das zu tun, was Ihre Anwendung benötigt, sind in Schwierigkeiten.

Ich widerspreche zwar nicht ganz, aber ich verstehe nicht wirklich, wie relevant das ist.Diese Seite gibt es speziell, weil Programmierer nicht immer alle Antworten haben.

Wenn Ihre Anwendung so komplex ist, dass eine Drosselung der Anzahl der von Ihnen verwendeten Threads erforderlich ist, möchten Sie dann nicht fast immer mehr Kontrolle, als das Framework Ihnen bietet?

NEIN.Wenn ich einen Thread-Pool benötige, verwende ich den bereitgestellten, es sei denn und bis ich feststelle, dass er nicht ausreicht.Ich gehe nicht einfach davon aus, dass der bereitgestellte Thread-Pool für meine Anforderungen nicht ausreicht, ohne dies zu bestätigen.

Ich spreche hier nicht als jemand mit nur theoretischen Kenntnissen.Ich schreibe und verwalte Anwendungen mit hohem Volumen, die stark Multithreading nutzen, und finde, dass der Thread-Pool im Allgemeinen nicht die richtige Antwort ist.

Den Großteil meiner Berufserfahrung habe ich mit Multithreading- und Multiprocessing-Programmen gesammelt.Ich musste oft auch meine eigene Lösung entwickeln.Das bedeutet nicht, dass der Thread-Pool in vielen Fällen nicht nützlich oder angemessen ist.Der Thread-Pool ist für die Verarbeitung von Arbeitsthreads ausgelegt.In Fällen, in denen mehrere Worker-Threads geeignet sind, sollte im Allgemeinen der bereitgestellte Thread-Pool der erste Ansatz sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top