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();
Kann mir da jemand einen Tipp geben?
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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