Laden...

Konzept Multithreadding in GUI Anwendung

Erstellt von Wolf_maYer vor 17 Jahren Letzter Beitrag vor 17 Jahren 1.836 Views
Wolf_maYer Themenstarter:in
286 Beiträge seit 2006
vor 17 Jahren
Konzept Multithreadding in GUI Anwendung

Hi,
Ich bin mir jetzt nicht gerade sicher, ob dass Thema hier richtig angesiedelt ist, da es mit MT, Design und GUI zu tun hat. Aber ich versuche hier mal mein Glück.

Ich möchte eine Anwendung schreiben, die Daten aus einer DB anzeigt und bei Userwunsch auch ändert.
Die zu verarbeitenden Datenmengen sind nicht immer sehr klein so dass bei bestimmtem Operationen der Benutzer eine ruhende Applikation vor sich hat.
Um dieses unangenehme Verhalten zu umgehen, möchte ich die Datenoperationen in einen neuen Thread auslagern.

Damit der Benutzer aber nicht auf die Idee kommt nebenher eine zweite Operation anzustoßen möchte ich die GUI wärend der Abarbeitung ruhig stellen (einfrieren) und einen Info-Dialog mit einer ProgressBar und einigen Informationen zu der laufenden Operation im Vordergrund anzeigen.

Dieser Dialog soll dem Benutzer auch die Möglichkeit bieten die komplette Operation abzubrechen, falls sie ihm zu lange dauert.

Dies zu meinem Problem, nun zu meiner Frage:

Wie designe ich das?
Also ich habe die Haupt-GUI,
die Klassen für die Datenhaltung,
die Klasse/n für die Datenverarbeitung
und die Datenbankverbindung.

Die Verbindung zur Datenbank soll nicht neu aufgebaut werden sondern immer weiter genutzt werden. Wie friere ich die Gui ein und wie stelle ich den Info-Dialog dar?

Mir fehlt der Ansatz, wie ich diese Probleme lösen soll und hoffe, dass ihr mir ein bisschen unter die Arme greifen könnt.

Gruß, maYer

B
1.529 Beiträge seit 2006
vor 17 Jahren

Du erstellst dir einen eigenen Dialog, so wie du ihn benötigst (ProgressBar, Buttons, Labels etc.). Dann startest du von der MainForm den WorkerThread und zeigst deinen Dialog mittels ShowDialog modal an. Der WorkerThread kann die ProgressBar etc. per Invoke ändern und schließt ihn nach Abschluss der Arbeit wieder. Danach kehrt ShowDialog wieder zurück und du machst weiter.

Wolf_maYer Themenstarter:in
286 Beiträge seit 2006
vor 17 Jahren

Hi Borg,
danke für deine Antwort. Das war der Ansatz, auf den ich einfach nicht gekommen bin. Mag daran liegen, dass es für mich der Anfang vom MultiThreadding ist aber ich möchte dich hier nicht mit meinen persönlichen Problemen weiter langweilen und komme zurück zum Topic.

Ich habe aber leider nicht nur eine Operation, die von Benutzer ausgelöst werden kann und so wie ich das verstanden habe, ist die Thread-Abarbeitung in der Methode ThreadMain enthalten. Sollte ich dann für jede Operation einen eigenen Thread bauen, der dann angestoßen wird?

Kann ich eine ThreadKlasse mit den allgemeinen Aufgaben wie zum Beispiel das aktualisieren der Progressbar und ändern des Anzeigetextes schreiben die von der eigentlichen Threadklase abgeleitet ist und die implementieren? Ist das möglich und hälst du das für praktikabel?

Gruß, maYer

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von Wolf_maYer

Kann ich eine ThreadKlasse mit den allgemeinen Aufgaben wie zum Beispiel das aktualisieren der Progressbar und ändern des Anzeigetextes schreiben die von der eigentlichen Threadklase abgeleitet ist und die implementieren?

Im Prinzip gibts das schon und nennt sich BackgroundWorker. Diese Klasse ist für nebenläufige Aufgaben gedacht, die vom GUI angestoßen werden. Ist einfacher als direkt Threads zu nutzen.

B
1.529 Beiträge seit 2006
vor 17 Jahren

Einen Thread zu starten ist doch aber nicht schwer.
Und da du für verschiedene Aufgaben sowieso verschiedene Methoden verwendest, stellt es ja kein Problem dar, diese jeweils in einem neuen Thread zu starten.
Mittels ParamterizedThreadStart (such mal hier im Forum danach) kannst du auch Parameter an den Thread übergeben. Das kann auch eine eigene Klasse sein, die Unmengen von Informationen enthalten kann. Aus dieser kann der Thread entnehmen, was er tun soll und seine Rückgabe speichern.

Also kannst du grundsätzlich so vorgehen:

internal class WaitDialog : Dialog
{ // ... }

internal class myThreadData
{
   public WaitDialog progress;
   // was auch immer
}

private void myWorkerThread( object obj )
{
   myThreadData data = obj as myThreadData;
   if (obj == null)
   {
      return;
   }
   // tue was auch immer, speichere Ergebnisse in data
   // aktualisiere ab und zu den Dialog über data.progress.Invoke
   // am Ende den Dialog über Invoke schließen
}

private void DialogZeigenUndArbeiten()
{
   myThreadData data = new myThreadData();
   // Infos in data setzen
   data.progress = new WaitDialog();
   (new Thread(new ParameterizedThreadStart(myWorkerThread))).Start(data);
   data.progress.ShowDialog();
   // ergebnisse aus data auslesen
}

EDIT:

Im Prinzip gibts das schon und nennt sich BackgroundWorker.

Stimmt. Ich glaube, die Verwendung des BackgroundWorker macht die Sache für dich auch deutlich einfacher...

Wolf_maYer Themenstarter:in
286 Beiträge seit 2006
vor 17 Jahren

Hi,
Das funktioniert soweit.
Ich habe aus der Gui eine Methode aufgerufen, die den Dialog aufbaut, den BGWorker startet und anschließend den Dialog anzeigt.

Über Invoke kann ich bestimmte Werte ändern und das schließen durch setzen einer Boolschen Variable die auf dem Dialog mit einem Timer abgefragt wird initiieren. Top.

Wenn ich den selben Thread allerding noch einmal starte (immer hintereinander und nicht zeitgleich!!!) bekomme ich die Fehlermeldung:
Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.

Darunter kann ich mir allerdings nichts vorstellen.

Gruß, maYer

Wolf_maYer Themenstarter:in
286 Beiträge seit 2006
vor 17 Jahren

So,
ich bin von einem BackGroundWorker abgewichen und nutze nun einen ParameterizedThread. Den initialisiere ich auch jedesmal neu und der Fehler tritt nicht mehr auf.

Trotzdem werde ich mir noch einmal ein paar Hintergrundinfos anlesen, da dieses Thema ja nicht ohne ist.

Danke nochmal für die Hilfe!!

Kann geschlossen werden.

Gruß, maYer