Laden...

Erstellen eines reinen Wartedialogs in einem anderen Thread

Erstellt von lukasS vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.870 Views
lukasS Themenstarter:in
65 Beiträge seit 2009
vor 8 Jahren
Erstellen eines reinen Wartedialogs in einem anderen Thread

Hallo,

ich habe einen Wartedialog erstellt. Dieser wird aufgerufen, wenn ich z. B. nach bestimmten Dateien in einem Ordner scanne und/oder noch andere Sachen im Hauptdialog beim Startvorgang passieren.

Was ich mache ist, ich scanne Ordner im Haupt-Thread.
Dabei rufe ich eine static-Funktion startWaitingForm.
Diese Funktion erstellt mir einen neuen Thread in dem der Wartedialog laufen soll.


      private static frmWaiting frmWait;
      private static Thread thWait;

      public static void startWaitingForm()
      {
         if (thWait != null)
         {
            if (thWait.IsAlive)
               thWait.Abort();
         }

         thWait = new Thread((ShowWaitDialog));
         thWait.Start();

      }

      private static void ShowWaitDialog()
      {
         frmWait = new frmWaiting();
         frmWait.ShowDialog();
      }

Während des Scan-Vorgangs rufe ich die static-Funktion updateWaitingForm, die einen Wert als Parameter hat, auf. Dieser Wert soll in dem Warte-Dialog angezeigt werden.


      public static bool updateWaitingForm(string sTitle, string sPath)
      {
         if (frmWait == null)
            return true;

         if (frmWaiting.bCancel)
            return false;

         if (frmWait.InvokeRequired)
         {
            updateWaitForm callback = new updateWaitForm(updateWaitingForm);
            frmWait.Invoke(callback, new object[] { sTitle, sPath });
         }
         else
         {
            frmWait.updateWaitingForm(sTitle, sPath);
         }

         return true;
      }

Nach dem Scan-Vorgang rufe ich zum Schluss die closeWaitingForm auf. Diese soll den Dialog und Thread schließen.


      public static void closeWaitingForm()
      {
         if (frmWait == null)
            return;

         if (frmWait.InvokeRequired)
         {
            closeWaitForm callback = new closeWaitForm(closeWaitingForm);
            frmWait.Invoke(callback);
            thWait.Abort();
         }
         else
         {
            frmWait.Close();
         }
      }

Im Normalfall würde man den Scan-Vorgang in einen anderen Thread verlegen, allerdings möchte ich nur den Warte-Dialog in einem anderen Thread habe und nur den Text ändern lassen. Es passieren nämlich noch einige Sachen später in dem Hauptdialog (Bäume werden aufgebaut, Tabellen gefüllt etc.). Dabei soll der Dialog halt offen bleiben.

Der ganze Vorgang funktioniert, allerdings wenn sich keine und sehr wenige Datei in dem Ordner befinden, kommt wohl das Schließen zu schnell oder ähnliches und es kommt zu einem Absturz oder manchmal schließt sich der Warte-Dialog nicht. Wenn ich das langsam im Debugger durchlaufe, läuft alles.
Ich sehe leider den Wald vor lauter Bäumen nicht mehr. Ich habe schon so viel damit herum experimentiert, leider alles ohne ERfolg. Leider konnte ich noch kein Beispiel finden, wo der Wartedialog-Text einfach so geändert wird vom Haupt-Thread.

Ich weiß jetzt nicht ob mein Ansatz so weit richtig ist, deshalb frage ich halt hier 🙂
Gerne tue ich noch die paar Zeilen Code vom Dialog rein, wenn notwendig.

Was genau mache ich falsch ?( 🤔

Danke schon mal!!!

Lukas

F
10.010 Beiträge seit 2004
vor 8 Jahren

Ich sehe leider den Wald vor lauter Bäumen nicht mehr. Ich habe schon so viel damit herum experimentiert, leider alles ohne ERfolg

Ich weiß jetzt nicht ob mein Ansatz so weit richtig ist

Nein, dein Ansatz ist komplett falsch.

Die UI wid immer im Hauptthread verwaltet, die Aktion musst du in einem Extra Thread durchführen.
"Bitte warten"-Fenster anzeigen während Daten geladen werden

F
174 Beiträge seit 2007
vor 8 Jahren

Sehe ich das falsch, oder hast du mit deiner Implementierung der Funktion "updateWaitingForm" eine Endlos-Schleife produziert? Aus meiner Sicht tut die nämlich gar nichts, ausser sich die ganze Zeit selber wieder aufzurufen.

lukasS Themenstarter:in
65 Beiträge seit 2009
vor 8 Jahren

Hallo zusammen und danke schön erstmal!

Nein, dort ist keien Endlos-Schleife, sonst würde es ja nicht funktioniert wenn mehrere Objekte gescannt werden. Das Invoke ruft zwar die selben Funktion auf, diese wandert dann aber nicht mehr in den IF-Zweig, sondern in das ELSE wo dann die Texte gesetzt werden.

Im Moment baue ich das ganze um. FZelle gab mir den link zu einem anderen Thread wo das Stichwort Splash-Screen auftauchte. Das brachte mich auf Yet Another Splash Screen in C# wo allerdings der selbe Fehler vorkommt, den ich auch habe (Dialog wird geschlossen, während der noch nicht aufgebaut wurde). Aber dennoch bringt mich das erstmal weiter.

Lukas

F
174 Beiträge seit 2007
vor 8 Jahren

Ich sehe aber im ELSE-Zweig bisher nur das hier:

frmWait.updateWaitingForm(sTitle, sPath);

Und das ruft eben genau diese Funktion wieder auf, ohne irgendeinen Status zu aktualisieren. Oder ist der Code den du gepostet hast nicht aktuell?

W
955 Beiträge seit 2010
vor 8 Jahren

Hi,

warum verwendest du nicht die TPL? Also das Arbeiten mit Tasks, async und await? Dann kannst du das Scannen in einem Task auslagern und die GUI friert nicht ein. Des weiteren könntest du dich mit den Producer/Consumer-Pattern beschäftigen, also eine Akteur schaufelt sich durch die Platte und bietet die Dateiinhalte an während die anderen diese Daten verarbeiten.

lukasS Themenstarter:in
65 Beiträge seit 2009
vor 8 Jahren

Ich sehe aber im ELSE-Zweig bisher nur das hier:

frmWait.updateWaitingForm(sTitle, sPath);  

Und das ruft eben genau diese Funktion wieder auf, ohne irgendeinen Status zu aktualisieren. Oder ist der Code den du gepostet hast nicht aktuell?

Ach,das hast du gemeint. Der Code ist nicht komplett. Es ist eine Funktion in dem frmWait, die genauso heißt. Die Sachen hier die sind in einer anderen Klasse.
Ich wollte jetzt nicht alles hier reinstellen, weil das zu viel wäre. Aber stimmt, für eine bessere Verdeutlichung hätte ich das zum Teil umschreiben sollen.

F
174 Beiträge seit 2007
vor 8 Jahren

Nagut. Du greifst aber zumindest auf die gleiche Instanz zu (immer frmWait). Das bedeutet, dass es eben doch die gleiche Funktion ist. Also entweder ich bin total blind, oder deine eigene Namensgebung ist dir jetzt auf die Füße gefallen.

Würde Möglichkeit 1 aber auch nicht ausschließen 😃

lukasS Themenstarter:in
65 Beiträge seit 2009
vor 8 Jahren

Hi,

warum verwendest du nicht die TPL? Also das Arbeiten mit Tasks, async und await? Dann kannst du das Scannen in einem Task auslagern und die GUI friert nicht ein. Des weiteren könntest du dich mit den Producer/Consumer-Pattern beschäftigen, also eine Akteur schaufelt sich durch die Platte und bietet die Dateiinhalte an während die anderen diese Daten verarbeiten.

Interessante Idee, danke für den Tipp! Wenn mir bisschen Zeit übrig bleibt, schaue ich es mir mal an.

S
322 Beiträge seit 2007
vor 8 Jahren

Hallo,

vielleicht kannst Du was von einem Splashscreen abschauen, hier ein Beispiel:
http://www.codeproject.com/Articles/5454/A-Pretty-Good-Splash-Screen-in-C

Grüße
Steffen