JobList-Klasse
Arbeitet Aufgaben (Jobs) mit einer bestimmten Anzahl von Worker-Threads parallel im Hintergrund ab, um die Rechenleistung von Mehrkernprozessoren optimal zu nutzen.
Das Problem
Mit mehrkernigen Prozessoren steigt theoretisch auch die Rechenleistung fast linear an – aber nur, wenn die Aufgaben auch parallelisiert werden können. Oft werden mehrere gleichartige Aufgaben nacheinander durchgeführt, wie z. B. das Erstellen von Berichten oder Diagrammen in verschiedenen Ansichten. Die Reihenfolge dieser Arbeiten ist in der Regel egal, also kann man sie oft auch gleichzeitig ausführen. Selbst dei einer geringen Anzahl physischer CPUs oder Kerne kann eine Parallelisierung der Aufgaben die Gesamtzeit verringern, wenn die Aufgaben häufige Wartepausen einlegen, in denen z. B. auf Netzwerkantworten gewartet wird.
Die Lösung
Die JobList-Klasse vereinfacht die parallele Ausführung solcher Aufgaben enorm. Die Verwendung ähnelt ein bisschen der BackgroundWorker-Klasse, aber die gesamte Job-Listenverwaltung ist auch schon mit drin. Jeder Aufgabentyp besteht aus einer Klasse, die von der abstrakten Basisklasse Job
abgeleitet ist. Jeder Aufgabeninstanz können über ihren Konstruktor individuelle Anweisungen wie Dateinamen oder Selektionskriterien mitgegeben werden. Die Job
-Instanzen werden dann nur noch einer JobList
-Instanz hinzugefügt und schon beginnt die Bearbeitung der Aufgaben. Sobald eine Aufgabe abgeschlossen ist, wird die nächste wartende Aufgabe in einem freien Worker-Thread gestartet. Um eine Überlastung zu vermeiden, ist die Anzahl der Threads begrenzt und auf die doppelte Anzahl der verfügbaren CPU-Kerne voreingestellt (konfigurierbar). So wie weitere Aufgaben anfallen, können diese einfach weiter der JobList
hinzugefügt werden, auch wenn noch nicht alle anstehenden Aufgaben abgeschlossen sind. Wenn das der Fall ist, wird ein Ereignis ausgelöst, auf das die Benutzeroberfläche mit einer Meldung oder Anzeige reagieren kann. Zwischenmeldungen zum Fortschritt sind ebenfalls verfügbar.
Kompatibilität:
Beispiel
Der folgende Beispielcode zeigt, wie die JobList-Klasse verwendet werden kann. Es werden mehrere Diagramme parallel nach verschiedenen Spezifikationsdateien in verschiedenen Größen erstellt. Die eigentliche Arbeit wird in der PlotJob.DoWork
-Methode implementiert.
{
// …
private void GenerateGraphs(IEnumerable<PlotSpec> specs)
{
// Create the JobList instance
JobList plotJobs = new JobList();
// Know when one of the jobs fails
plotJobs.JobError += new EventHandler<JobListErrorEventArgs>(plotJobs_JobError);
// Add all jobs to the list to have them worked off
foreach (var spec in specs)
{
Job job = new PlotJob(spec.FileName, spec.CustomSize);
plotJobs.AppendJob(job);
}
// Wait for the last one to complete
plotJobs.JoinAll();
}
private void plotJobs_JobError(object sender, JobListErrorEventArgs e)
{
// Just print out the full error details for now
Console.Error.WriteLine(e.Error.ToString());
}
}
// This class defines what a "Plot Job" is about and what to do.
// There can be other inherited classes that do other work and you can add
// any of them to one single JobList.
class PlotJob : Job
{
private string fileName;
private Size customSize;
// Initialises a new instance of the PlotJob and sets the parameters of
// the work to do.
public PlotJob(string fileName, Size customSize)
{
this.fileName = fileName;
this.customSize = customSize;
}
// This method does the work. It is called by the JobList on a worker thread.
public override void DoWork()
{
Common.PlotBySpec(fileName, customSize, true);
// Just return when you're finished, the next pending job will start
// right away, if there is one left.
}
}
Download
JobList.cs9,0 KiBQuelltext der JobList-Klasse
Änderungen
- Fehler werden über das
JobError
-Ereignis gemeldet. - Anzahl der Worker mit doppelter CPU-Anzahl statt 3 vorbelegt
JoinAll
-Methode hinzugefügt: Zeitlich begrenztes Warten auf den Abschluss aller Jobs.- Code-Dokumentation erweitert.
Lizenz und Nutzungsbedingungen
Vervielfältigung und Weiterverbreitung dieser Datei, verändert oder unverändert, sind gestattet, vorausgesetzt die Urheberrechtsangabe und dieser Hinweis bleiben erhalten. Diese Datei wird wie vorliegend ohne jegliche Garantie oder Gewährleistung angeboten. (GNU All-Permissive-Lizenz)
Statistische Daten
- Erstellt am 2008-11-02, aktualisiert am 2012-02-09.
- Ca. 150 Codezeilen, geschätzte Entwicklungskosten: 150 - 600 €