Backgroundworker - Warten bis abgeschlossen

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Backgroundworker - Warten bis abgeschlossen

    Hallo,

    Ich habe einen Backgroundworker, den ich mit bgw.RunWorkerAsync() starte.
    Gibt es eine Möglichkeit, dass der Code nach diesem Aufruf erst weiterfährt, wenn der Backgroundworker fertig ist?

    Das Problem ist, dass ich den Backgroundworker mehrmals aufrufe und dann die Meldung kommt, er sei ausgelastet.
    Wenn ich aber keinen Backgroundworker verwende, bleibt die Form einfach hängen..

    Gruss
    sandiro
    es gibt beim Backgroundworker ein event das "RunWorkerCompleted" oder so ähnlich heißt ...
    kannst ja beim starten des bgw form.enable auf false setzten un wenn er fertig is wieder auf true
    Also ich rufe den BGW mehrmals nacheinander auf und wenn ich ihn das zweite Mal aufrufe hat er den Code noch nicht fertig abgearbeitet.
    Ich muss also bei jedem Aufruf zuerst warten, bis er den Code fertig hat...

    Gruss
    sandiro

    Edit:
    @skyscater;
    Also muss ich einfach abfragen, ob der BGW nicht beschäftig (IsBusy) ist und falls nicht, kann ich ihn erneut aufrufen?
    Also der Backgroundworker wird nur 1x vom User aufgerufen und danach mehrmals vom Code - ich hab dies nun geändert.
    Der BGW wird nun nur einmal aufgerufen und führt alle Aktionen durch, dann funktionierts.

    Danke und Gruss
    sandiro
    Ich hänge mich hier dran, weil es die gleiche Frage ist.

    Aber, was macht man, wenn man mehrere Backgroundworker hat, die beendet sein müssen?

    Bei einem ist es klar, man kann seine Routinen in das "Completed" Ereignis setzen.
    Sollte man etwa eine Variable verwenden, die von jedem BGW heruntergezählt wird,
    und getestet, ob sie schon 0 ist, oder gibt es da eine bessere Lösung?
    Ein BGW bzw. ein Thread sind Dinger, die kein synchrones Ende haben, das ist ihre Bestimmung.
    Sie werden neben dem Hauptthread gestartet und sie können über Events Daten austauschen und das Ende signalisieren.
    Was dazwischen passiert, ist nicht mal in Bills Hand.
    Kannst Du ggf. Dein Vorhaben etwas detaillierter beschreiben?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wenn Arbeit parallel ausgeführt wird, kann man zum Beispiel über Events, eine Zählvariable und Monitoring den GUI-Thread über das Ende der asynchronen Operationen informieren. Hierbei dekrementiert jeder Thread die Zählvariable, sobald er ausgeführt wird und inkrementiert sie wieder, sobald er wieder aktiv wird. Sobald der Wert 0 annimmt, wird ein Ereignis ausgelöst (im beschriebenen Fall ist das halt im Vgl. zum Semaphor vereinfacht dargestellt).
    Wäre in dem Fall wahrsch. sogar besser, als der Semaphor.

    Gruß
    ~blaze~
    Das was ~blaze~ geschrieben hatte war auch meine Idee, wusste aber nicht, ob das gängige Praxis ist.

    Es geht um ein Projekt, das ich neulich schon mal erwähnt hatte.
    Ich lese Daten mittels einer Drittanbieter-Klasse in Arrays und Listen ein.

    Teilweise mache ich statistische Berechnungen,
    Teilweise grafische Darstellung von Histogramm und Trend.
    Es bot sich an, diese Berechnungen asynchron ausführen zu lassen,
    damit der User nicht zu lange warten muss.

    Jetzt lese ich also erst mal die Daten ein
    Dann starte ich nacheinander die BGWs für
    Statistik
    Trend
    Histogramm

    Ich muss nun aber wissen, wann alle BGWs fertig sind, um
    z.B. den Startbutton wieder frei zu geben u.ä.
    Ich würde im Completed-Event eines jeden BGW abfragen, ob noch abhängige BGWs aktiv sind.
    Wenn nein, die Formfunktionen wieder aktivieren.
    Für die Aktivprüfung kannst du das IsBusy-Flag nehmen, wenn bei jedem BGW-Start die Formfunktionen deaktiviert werden.
    Bedenke, dass theoretisch ein BGW bereits fertig sein könnte, bevor du den zweiten startest.

    Ganz wasserdicht ist es, wenn du eigene Flags nimmst, die du alle vor dem ersten BGW-Start initialisierst und im Completed-Event wieder zurücksetzt.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Das müsste man dann aber über ein gemeinsames Objekt machen, das per SyncLock gesperrt wird. Sonst kann es sein, dass ein BGW während der Abfrage auf IsBusy noch aktiv ist. BackgroundWorker würde ich aber eher nicht verwenden, sondern direkt über ThreadPool- oder eigene Threads arbeiten.
    @petaod: Theoretisch könnte es doch sogar passieren, dass zwischen Auslesen und Setzen der Flags ein Setzvorgang stattfindet. Interlocked bietet ja Or glaub' ich nicht an. Was man auf jeden Fall machen könnte, wäre per Interlocked zu dekrementieren und wenn der Wert dann 0 ist (bzw. der zu erreichende Zielwert), wird das Programm abgeschlossen.

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    Theoretisch könnte es doch sogar passieren, dass zwischen Auslesen und Setzen der Flags ein Setzvorgang stattfindet.
    Stimmt.
    Ich glaube da muss man dann doch Interlock-Techniken anwenden, so wie du's beschreibst und hier ausführlich dokumentiert ist.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Naja, es erleichtert die Verwendung im GUI-Bereich geringfügig, da man sich nicht um die ganzen Threading-Sachen selber kümmern muss, aber eigentlich ist es eher sinnlos, extra eine Komponente für ein paar Callbacks per Invoke zu machen, etc. Wie gesagt, BGWs kapseln einfach einen Thread - vmtl. aus dem ThreadPool. Meist kann man das selber problemlos, insofern ist halt der BGW überflüssig. Um mehr als einen BGW zu verwenden, müsste man mehrere Komponenten oder sogar per Code erzeugen. Dann wär's halt komplett überflüssig - und 10 BGW auf einer Form...

    Gruß
    ~blaze~