Und schon bin ich beim nächsten Multithreading-Problem.
Stark vereinfacht hat meine Anwendung zwei Threads. Den Hauptthread, dem die
GUI gehört und der diese u.U. recht häufig aktualisiert, und einen Ladethread, der im Hintergrund Daten lädt. Die
GUI zeigt die Daten auf dem letzten Stand an. Wenn jetzt also mehr Daten geladen sind, muss die
GUI das irgendwo her wissen, denn vom Prinzip her ist sie Event-basiert, so dass ich ein Polling eher für unglücklich halte. Also haben die Klassen, die die Daten laden, ein Event, in das sich die
GUI einträgt. Wenn ich das Event jetzt aber vom Ladethread aus auslöse, wird es im selben Thread abgearbeitet, nicht im
GUI-Thread. Es scheint Myriaden Möglichkeiten zu geben, das zu erreichen, aber welche soll ich denn nehmen?
Nur um nichts falsch zu verstehen, es handelt sich um einen Hintergrund-Thread. Die
GUI nimmt zwar immer die neuesten Daten, die der Thread geladen hat, aber sie wartet nicht explizit darauf, sondern man arbeitet ganz normal weiter. Ist also keine Fortschritts-Balken-Geschichte.
Am tollsten wäre es, wenn es eine Möglichkeit gäbe, dem Event zu sagen, dass es im
GUI-Thread ausgeführt werden soll. Das scheint aber nicht zu gehen. Eine Möglichkeit, die ich gefunden habe, sieht stilisiert ungefähr so aus:
Code:
void ShowProgress(object param)
{
if(!InvokeRequired) {
// Update
GUI
} else {
ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress);
Invoke(showProgress, param);
}
}
Nun wird es voraussichtlich bei mir nur ein oder zwei solche Events geben, so dass sich der Aufwand in Grenzen hält. Erinnert mich aber immer etwas an die unschöne fork()-Geschichte unter Unix. Der Vorteil ist halt, dass ich das Event einfach auslösen kann, wo ich will, und es sorgt selbst dafür, im richtigen Thread zu landen (es soll hier mal nicht stören, dass das Beispiel weniger für ein Event als für einen Delegaten gedacht war). Der Ladethread kann Control.Invoke() natürlich von sich aus nicht aufrufen, da er von der
GUI nichts weiß, so dass das flachfallen würde. Ist diese Methode also vernünftig?
Oh, dann gäbe es noch als Alternative den BackgroundWorker. Hier habe ich mich noch nicht ganz so weit eingearbeitet. Dort gibt es einerseits ein Event, das die eigentliche Arbeit in einem separaten Thread ausführt, und umgekehrt können von diesem Thread aus dann einige Events im Original-Thread aufgerufen werden (zumindest scheint es so), die eine Fortschrittsanzeige ermöglichen oder das Ende des Threads ankündigen. Passt jetzt nicht hundertprozentig zu meinem Problem, denn ich brauche Benachrichtigungen, wenn neue Daten vorliegen, während der eigentliche Fortschritt mich überhaupt nicht interessiert. Wenn ich also dafür ein Event missbrauche, dem man eigentlich eine Prozentzahl mitgeben soll, hat das irgendwie etwas verruchtes, aber vielleicht bin ich da kleinlich
Also, was sagt jemand, der sich damit auskennt? Die "fork"-Geschichte? Oder einfach mit dem BackgroundWorker arbeiten? Oder was ganz anderes?