Laden...

Thread mit paralleler Berabeitung die in Hintergrund arbeitet

Erstellt von oehrle vor 10 Jahren Letzter Beitrag vor 10 Jahren 745 Views
Thema geschlossen
O
oehrle Themenstarter:in
461 Beiträge seit 2009
vor 10 Jahren
Thread mit paralleler Berabeitung die in Hintergrund arbeitet

Hallo, habe mich am Wochenende mit der TPL beschäftigt, da ich im Moment mit einer Applikation dehr viel Daten und Dateien bewegen, organidieren und Daten filtern sowie aufbereiten muss. Somit habe ich einige Bearbeitungen parallelisiert (da wir Mehrkernmaschinen im Einsatz haben) mit gutem Erfolg (zeigt die Zeitmessung).
Nun aber noch zu meinem Problem, wo ich noch nicht so richig verstehe. Ich habe in meiner Applikation mit einer Menuleiste, bei der man bei Klick auf die Menupunkte verschiedene Abarbeitungen aufruft (Klassen), die Daten aufbereiten und visualisieren. Solange die Abarbeitung läuft, kann ich aber keine anderen Menupunkte anklicken, damit diese auch schon weitere Dinge machen könnten.
Ich habe allerdings auch schon einen Menupunkt in einem eigenen Thread gestartet, dann friert die Oberfläche nicht ein und ich kann einen weiteren Menubutton anklicken.
Da habe ich jetzt auch so probiert, mit der parallelen Abareitung, aber ohne Erfolg.
Deswegen meine Frage zum folgenden Code:


 //// Thread starten, wenn Menubutton geklickt wird
                new Thread(() =>
                {

                    //// parallele Bearbeitung
                    Parallel.Invoke(()=> { GibMeldungStartAus(); }, ()=>{GibMeldungEndeAus();});

                    //// weitere Bearbeitungen
                    Task t1 = new Task(() => {IchMachAuchNochEtwasFürDatenausgabe();});
                    Task t2 = new Task(() => {IchMachAuchNochEtwasZusätzlichesFürDatenausgabe();});

                    //// Warten, bis die Tasks fertig sind
                    Task.WaitAll(t1, t2);

                    //// Fenster anzeigen (muss noch in eine Dispatcher-Methode)
                    ZeigeDasAusgabeWindowAn();

                }).Start();

  1. ist es richtig einen Thread zu verwenden und zu starten, in dem dann intern die TPL verwendet wird?
  2. Was wäre die Alternative, damit meine Anwendung während der Bearbeitung nicht einfriert?

Kann mir da jemand einen Tipp geben?

16.834 Beiträge seit 2008
vor 10 Jahren

Die Variante via Invoke und zwei /mehrere Tasks zu deklarieren und zu starten ist im Endeffekt genau das gleiche.
Man sollte aber Tasks über Task.Factory.StartNew erstellen; das was Du machst ist die Tasks zwar erstellen - aber sie starten nicht.

So wie das für mich ausschaut vermischt Du hier die Threads mit der sonstigen GUI und Logik. Früher oder später wirst Du daher ein Fehler bzgl. Multithreading machen, da es unübersichtlich ist bzw. wird.
Besser ist es eine abgetrennte Klasse zu erstellen, dort ein Objekt erstellen, das in einem Thread läuft und irgendwelche Statusänderungen an die GUI via Events melden - die Logik eben auszulagern.
Die GUI muss es nicht interessieren, ob Du Aufgaben in Threads auslagerst - Du musss nur dafür sorgen, dass die GUI nicht hängt.

Zu 1: Ob das Richtig is sei mal dahin gestellt. Einbetten bzw. Kaskadieren sollte man TPL jedenfalls nicht (also eine parallele Schleife in eine parallele Schleife).
Aber insgesamt kann man das so oder so ähnlich tun - besser wäre aber definitiv das Auslagern. Ob der Hauptcontainer ein Thread oder ein Task ist... ich würde wohl ein Task nehmen.

Zu 2: keine. Du musst länger andauernde Aufgaben in ein Hintergrundkonstrukt (Thread / Task / BGW) auslagern.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo oehrle,

wenn du Tasks startest und dann mit WaitAll darauf wartest, bis sie fertig sind, solltest du dich nicht wundern, dass der aufrufende (GUI-)Thread blockiert, obwohl die Tasks brav in anderen Threads laufen.

Auch nur eine Variante von des in [FAQ] Warum blockiert mein GUI?, Abschnitt "Achtung: Noch eine Falle: Thread.Join" beschrieben.

Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 1.1 und 1.1.1.

Bei Tasks kann eine ContinueWhenAll angehängt werden, in der du das Aktualisieren des GUIs anstoßen kannst. Ein Warten auf die Tasks an der Aufrufstelle ist somit nicht notwendig.

Den Code, der die Tasks startet, in einem extra Thread zu starten, ist zwar möglich, aber in meinen Augen nicht besonders schön.

herbivore

Thema geschlossen