Laden...

[erledigt] BackgroundWorker Komponente blockiert GUI (Übung in DoWork)

Erstellt von HL1234 vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.769 Views
HL1234 Themenstarter:in
14 Beiträge seit 2007
vor 13 Jahren
[erledigt] BackgroundWorker Komponente blockiert GUI (Übung in DoWork)

Hallo,
also ich habe mich schon eine Stunde hier umgegeschaut aber nichts gefunden, was mit diesbezüglich hilft.
Ich mache eine Übung zum BackGroundWorker Thread. Im DoWork Event wird eine Schleife durchgeführt die eine Belastung simmulieren soll (so dass man einen Fortschrittsbalken sieht und den Thread vorzeitig abbrechen kann - habe ich soweit programmiert - funtioniert auch)

Das Problem: der Buchauthor verwendet statt einer umpfangreichen Berechnung in backgroundWorker1_DoWork(..) einfach Thread.Sleep(1000);
Das funktioniert dann auch wie erwartet ich kann die Form weiter nutzen während der Thread da so arbeitet.
Ich habe mir dann gedacht ich baue da mal etwas Reales ein was wirklich was macht ohne "Sleep" und siehe da, dass Ganze hängt, als wenn ich mit backgroundWorker1_DoWork(..) nur eine Methode und keinen seperaten Thread aufgerufen hätte. Ich vestehe nicht warum. Weis jemand was hier nicht funktioniert? Oder - was habe ich falsch verstanden?

      private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
      {

         int    iNoDW = (int)e.Argument;  //übergebenen Gesamtzeit aus dem Textfeld
         double dFn   = 0.0;              //Einzelergebnis der zeitaufwendigen Berechnung
         int    iN    = 50;               //für Test Y mal Berchnung für n=50 durchführen

         for (int y=1; y<=iNoDW; y++)
         {
            if (backgroundWorker1.CancellationPending) //Thread beenden ?
            {
               e.Cancel = true;
               return;
            }
            
            //hier zeitaufwendige Verarbeitung
            //Thread.Sleep(100);   //do some usefull....this is not usefully
                                   //Ohne Thread.Speep() wird aber die Form blockiert 
                                   // bis der Thread fertig ist 

            //Berechne Fibonacci-Folge y mal nach der "Formel von Moivre-Binet" (siehe Wiki-Datei.mht im Project)
            dFn = 1.0/Math.Sqrt(5.0) * ( Math.Pow( ((1+Math.Sqrt(5.0))/2.0), iN ) 
                                        -Math.Pow( ((1-Math.Sqrt(5.0))/2.0), iN)
                                       );
            //-------------------------------------------------------------------------------
            //Wieviel Prozent des Gesamtverarbeitung des Treads sind beendet? Und Übergeben...
            //progressBar1 wird eingestellt auf Minimum = 0; und Maximum = 100;
            int iProz = (int)((y * progressBar1.Maximum) / iNoDW);

            backgroundWorker1.ReportProgress(iProz, dFn); //Raises the ProgressChanged event.
         }

         //Übergabe des Ergebnisses, wenn BackgroundWorker Thread fertig ist
         e.Result = dFn;
      }

Gruß - Harald

S
902 Beiträge seit 2007
vor 13 Jahren

Hallo,

ich bin mir nciht sicher ob der Zugriff auf die progressbar in der DoWork-Methode damit zu tun hat.

mfg
serial

795 Beiträge seit 2006
vor 13 Jahren

Hi!

Wie groß ist iNoDW? ((Ich würde bei einer Großen Zahl nicht bei jedem Schleifendurchlauf den Fortschritt berichten, sondern nur, wenn jeweils 1% der Gesamtdurchläufe fertig sind.)

Wie sieht dein ProgressChaged-Event aus? ((Ich weis nicht sicher, ob das auch asynchron ausgeführt wird. Wenn ja, kann es daran liegen?

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
S
902 Beiträge seit 2007
vor 13 Jahren

HAllo,

@TheBrainiac: das ProgressChanged wird im richtigen SyncContext ausgeführt, daran kann es eigentlich nicht liegen.

mfg
serial

795 Beiträge seit 2006
vor 13 Jahren

@serial: Gut zu wissen :evil:

Ich vermute stark, dass du zu oft den Fortschritt aktualisierst (s.o.)

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
S
902 Beiträge seit 2007
vor 13 Jahren

Hallo,

oh das hba ich mir garnicht so genau angeschaut, aber wenn du zu oft aktualisierst, wirst du auch eine blockierende gui haben, da jede aktualisierung in den gui-thread invoked wird.

mfg
serial

HL1234 Themenstarter:in
14 Beiträge seit 2007
vor 13 Jahren

Hallo,
vielen Dank für die vielen Antworten:
die Idee das der backgroundWorker1.ReportProgress() zu oft aufgerufen wird scheint zu stimmen.
Ich habe dies mal auskommentiert - und siehe da die GUI, die Form ist wieder erreichbar. Mit einer kleinen Änderung geht es jetzt:


           ... 
           int iProzSav = 0;

           for (...)
           ...

            if (iProzSav < iProz)
            {
               backgroundWorker1.ReportProgress(iProz, dFn); //Raises the ProgressChanged event.
               iProzSav = iProz;
            }

Vielen Dank!

Gruß - Harald