C# Multithreading bei Datei-E / a (Lesen)
Haben wir eine situation, wo unsere Anwendung verarbeitet werden muss, eine Reihe von Dateien, und statt ausführen dieser Funktion synchron, möchten wir beschäftigen multi-threading, um die workload-split unter verschiedenen threads.
Jedes Element der Arbeit ist:
1. Öffnen Sie eine Datei nur Lesen
2. Verarbeiten der Daten in der Datei
3. Schreiben der verarbeiteten Daten in einem Wörterbuch
Möchten wir ausführen, jede Datei die Arbeit an einem neuen thread?
Ist das möglich, und sollten wir besser die Verwendung der ThreadPool-oder laichen neue threads im Auge zu behalten, dass jedes Element der "Arbeit" dauert nur 30ms jedoch ist es möglich, dass Hunderte von Dateien die verarbeitet werden müssen.
Irgendwelche Ideen, um diese effizienter zu gestalten, begrüßt.
EDIT: Im moment sind wir die Nutzung der ThreadPool, um diese zu bewältigen. Wenn wir 500 Dateien verarbeiten wir radeln durch die Dateien und ordnen Sie jeder "Einheit von Bearbeitung" auf den threadpool verwenden QueueUserWorkItem.
Ist es geeignet, um die Verwendung der threadpool-für diese?
- Wenn eine serielle Verarbeitung erforderlich ist vielmehr eine synchrone Verarbeitung, dann einfädeln ist definitiv der falsche Weg.
- der Prozess oben aufgeführten Nummern 1 bis 3) sind eine komplette Einheit der Arbeit. wir haben vielleicht Hunderte von diesen zu erfüllen, ist nicht erforderlich, zu sychronously verarbeitet.
- Es ist eine Verschwendung von Zeit. Sie brauchen mehr Laufwerke, nicht mehr CPU-Kerne/threads.
- Definieren Sie "verarbeiten." Sind Sie im Grunde nur das Lesen der Datei, oder machst du irgendeine Art von CPU-intensive Arbeit an den Inhalten?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde vorschlagen, Sie verwenden
ThreadPool.QueueUserWorkItem(...)
, in diese threads werden vom system verwaltet und die .net-framework. Die Chancen, Sie vernetzen sich mit Ihren eigenen threadpool ist viel höher. Also würde ich empfehlen, Sie zu verwenden Threadpool zur Verfügung gestellt von .net .Es ist sehr einfach zu bedienen,
YourMethod(object o){
Your Code here...
}
Für weitere Informationen Folgen Sie bitte dem link http://msdn.microsoft.com/en-us/library/3dasc8as%28VS.80%29.aspx
Hoffe, das hilft
Ich schlage vor, Sie haben eine begrenzte Anzahl von threads (sagen wir 4) und dann haben Sie sich auf 4 pools arbeiten. I. e. Wenn du 400 Dateien zum Bearbeiten 100 Dateien pro thread geteilt. Sie erzeugen dann die threads auf, und übergeben Sie jedem Ihrer Arbeit und lassen Sie Sie laufen, bis Sie abgeschlossen haben Ihre spezifische Arbeit.
Du hast nur eine bestimmte Anzahl von I/O-Bandbreite, so dass zu viele threads werden nicht bieten Vorteile, auch daran erinnern, dass ein thread braucht auch eine kleine Menge von Zeit.
Statt für den Umgang mit threads oder verwalten, thread-pools direkt ich würde vorschlagen, mit einem höheren level-Bibliothek, wie Parallel Extensions (PEX):
PEX Griff thread-management-gemäß den zur Verfügung stehenden Kernen und laden, während Sie sich zu konzentrieren über die business-Logik bei der hand (wow, das Klang wie eine kommerzielle!)
PEX ist Teil der .Net Framework 4.0 aber ein zurück-port auf 3,5 ist auch als Teil der das Reaktive Framework.
AsParallel
sollte es konvertieren, die processedContent Sammlung.Schlage ich vor, den CCR (Concurrency and Coordination Runtime) es sich um die low-level-threading-details für Sie. Für Ihre Strategie, ein thread pro Workitem kann nicht der beste Ansatz sein, je nachdem, wie Sie zu schreiben versuchen, um das Wörterbuch, denn Sie kann zu schweren Streit, seit Wörterbücher sind nicht thread-sicher.
Hier einige Beispiel-code über die CCR, eine Interleave funktionieren würde schön hier:
In die lange laufen, ich denke, Sie werden glücklicher sein, wenn Sie Ihre eigenen threads. So können Sie Steuern, wie viele ausgeführt werden und machen es einfach, den status zu berichten.
Queue
.Dictionary
zu halten Laufenden threads, sortiert nach IhrerManagedThreadId
.Verwenden
ThreadPool.QueueUserWorkItem
zur Ausführung jeder selbständige Aufgabe. Definitiv nicht Hunderte von threads. Das ist wahrscheinlich zu großen Kopfschmerzen.Die Allgemeine Regel für die Verwendung der ThreadPool ist, wenn Sie nicht wollen, zu befürchten, wenn die threads beenden (oder verwenden Mutexe, Sie zu verfolgen), oder sich sorgen über anhalten des threads.
So brauchen Sie zu befürchten, wenn die Arbeit getan ist? Wenn nicht, wird der ThreadPool ist die beste option. Wenn Sie möchten, um zu verfolgen den Fortschritt insgesamt, aufhören threads dann Ihre eigene Sammlung von threads am besten ist.
ThreadPool ist im Allgemeinen effizienter, wenn Sie wieder mit threads. Diese Frage wird Ihnen eine weitere ausführliche Diskussion.
Hth
Verwendung der ThreadPool-für jede individuelle Aufgabe ist definitiv eine schlechte Idee. Aus meiner Erfahrung diese neigt dazu, zu verletzen Leistung mehr als helfen es. Der erste Grund ist, dass ein erheblicher Aufwand erforderlich ist, nur um Aufgabe zuweisen, für die der ThreadPool auszuführen. Standardmäßig wird bei jeder Anwendung zugewiesen ist es, die eigenen ThreadPool initialisiert wird mit ~100 thread Kapazität. Beim ausführen von 400 Operationen in einem parallelen, dauert es nicht lange zum füllen der queue mit Anfragen und jetzt haben Sie ~100 alle threads konkurrieren um CPU-Zyklen. Ja die .NET framework macht einen guten job mit Drosselung und die Priorisierung der queue, allerdings habe ich festgestellt, dass der ThreadPool ist am besten Links für lang andauernde Operationen, die wahrscheinlich nicht sehr Häufig auftreten (laden einer Konfigurations-Datei, oder random web-Anfragen). Die Verwendung der ThreadPool-Feuer aus ein paar Operationen willkürlich ist viel effizienter als das ausführen Hunderte von Anfragen auf einmal. Angesichts der aktuellen Informationen, die beste Vorgehensweise wäre so etwas wie dies:
Erstellen Sie ein System.Threading.Thread (oder verwenden Sie einen SINGLE-ThreadPool-thread) mit einer Warteschlange, dass die Anwendung von post-requests zu
Verwenden Sie die FileStream-BeginRead und BeginWrite Methoden zur Durchführung der IO-Operationen. Dadurch wird die .NET framework für die Verwendung des einheitlichen API ' s zu Faden, und führen Sie die IO (IOCP).
Diese wird Ihnen 2 nutzt, ist, dass Ihre Anfragen werden immer noch parallel verarbeitet, während so dass das Betriebssystem zu verwalten, Zugriff auf das Dateisystem und threading. Das zweite ist, dass, weil der Engpass der überwiegenden Zahl der Systeme wird die Festplatte, können Sie implementieren eine benutzerdefinierte Priorität zu Sortieren und die Drosselung auf Ihre Anfrage-thread zu geben, mehr Kontrolle über die Ressourcenverwendung.
Derzeit habe ich schriftlich eine ähnliche Anwendung und die Nutzung dieser Methode ist effizient und schnell... Ohne threading oder drosseln mein Antrag wurde nur mit 10-15% CPU, das kann akzeptabel sein, für einige Operationen in Abhängigkeit von der Verarbeitung beteiligt, aber es machte mein PC so langsam, als ob ein Antrag wurde mit 80%+ der CPU. Dies war der Zugriff auf das Dateisystem. Der ThreadPool und IOCP-Funktionen egal, ob Sie Rucken den PC runter, also nicht verwirrt, Sie sind optimiert für Leistung, auch wenn diese Leistung bedeutet, dass Ihre Festplatte ist squeeling wie ein Schwein.
Das einzige problem das ich habe ist die Speicherauslastung lief ein wenig hoch (50+ mb) während der Prüfung phaze mit etwa 35-streams gleichzeitig öffnen. Ich arbeite derzeit an einer Lösung ähnlich der MSDN-Empfehlung für SocketAsyncEventArgs, mit einem pool zu ermöglichen, x die Anzahl von requests gleichzeitig in Betrieb, was letztlich führte mich zu diesem forum posten.
Hoffe, das hilft jemandem bei Ihrer Entscheidungsfindung in der Zukunft 🙂