Um die höchste Leistung bei gleichzeitig ausgeführten Einheiten zu erzielen, schreiben Sie Ihren eigenen Thread-Pool, in dem beim Start ein Pool von Thread-Objekten erstellt wird, und blockieren Sie (früher angehalten), bis ein Kontext ausgeführt wird (ein Objekt mit einer von implementierten Standardschnittstelle) dein Code).
So viele Artikel über Aufgaben vs. Threads vs. .NET ThreadPool bieten Ihnen nicht wirklich das, was Sie benötigen, um eine Entscheidung für die Leistung zu treffen. Aber wenn Sie sie vergleichen, gewinnen Threads und insbesondere ein Pool von Threads. Sie sind am besten auf die CPUs verteilt und starten schneller.
Was diskutiert werden sollte, ist die Tatsache, dass die Hauptausführungseinheit von Windows (einschließlich Windows 10) ein Thread ist und der Aufwand für das Umschalten des Betriebssystemkontexts normalerweise vernachlässigbar ist. Einfach ausgedrückt, ich konnte für viele dieser Artikel keine überzeugenden Beweise finden, unabhängig davon, ob der Artikel eine höhere Leistung durch Einsparen von Kontextwechsel oder eine bessere CPU-Auslastung beansprucht.
Nun zu ein bisschen Realismus:
Die meisten von uns brauchen keine deterministische Anwendung, und die meisten von uns haben keinen harten Hintergrund mit Threads, was beispielsweise häufig mit der Entwicklung eines Betriebssystems einhergeht. Was ich oben geschrieben habe, ist nichts für Anfänger.
Am wichtigsten ist es also zu diskutieren, was einfach zu programmieren ist.
Wenn Sie Ihren eigenen Thread-Pool erstellen, müssen Sie ein wenig schreiben, da Sie sich mit der Verfolgung des Ausführungsstatus, der Simulation des Suspendierens und Fortsetzens und dem Abbrechen der Ausführung befassen müssen - auch in einer anwendungsweiten Ausführung Herunterfahren. Möglicherweise müssen Sie sich auch Gedanken darüber machen, ob Sie Ihren Pool dynamisch vergrößern möchten und welche Kapazitätsbeschränkungen Ihr Pool haben wird. Ich kann ein solches Framework in einer Stunde schreiben, aber das liegt daran, dass ich es so oft gemacht habe.
Der einfachste Weg, eine Ausführungseinheit zu schreiben, ist möglicherweise die Verwendung einer Aufgabe. Das Schöne an einer Aufgabe ist, dass Sie eine erstellen und in Ihrem Code inline starten können (obwohl Vorsicht geboten sein kann). Sie können ein Stornierungs-Token übergeben, um es zu bearbeiten, wenn Sie die Aufgabe abbrechen möchten. Außerdem wird der Versprechungsansatz zum Verketten von Ereignissen verwendet, und Sie können einen bestimmten Werttyp zurückgeben. Darüber hinaus gibt es mit Async und Warten mehr Optionen und Ihr Code wird portabler.
Im Wesentlichen ist es wichtig, die Vor- und Nachteile von Tasks vs. Threads vs. .NET ThreadPool zu verstehen. Wenn ich hohe Leistung benötige, verwende ich Threads und bevorzuge die Verwendung meines eigenen Pools.
Eine einfache Möglichkeit zum Vergleichen besteht darin, 512 Threads, 512 Tasks und 512 ThreadPool-Threads zu starten. Am Anfang von Threads tritt eine Verzögerung auf (daher sollte ein Thread-Pool geschrieben werden), aber alle 512 Threads werden in wenigen Sekunden ausgeführt, während der Start von Tasks- und .NET ThreadPool-Threads bis zu einigen Minuten dauert.
Nachfolgend finden Sie die Ergebnisse eines solchen Tests (i5 Quad Core mit 16 GB RAM), bei dem alle 30 Sekunden ausgeführt werden. Der ausgeführte Code führt eine einfache Datei-E / A auf einem SSD-Laufwerk aus.
Testergebnisse