Gå til innhold

C#: BackGroundWorker forblir busy selv om den gjør seg ferdig.


Anbefalte innlegg

Har et problem med en backgroundworker som ikke vil gjøre jobben sin...

 

Når programmet starter opp, blir det sendt en del kommandoer automatisk til en annen maskin. Dette fungerer fint, men jeg må ha med en while (sender.IsBusy) { Thread.Sleep(10);} for å ikke få InvalidOperationException.

 

Problemet er så når jeg skal trykke på knapper i GUIet, som gjør at det sendes flere kommandoer til den andre PC-en. Den første kommandoen blir sendt, men etterpå er backgroundworkeren busy. Da ser det ut som om programmet har låst seg, men det er opptatt med å vente på backgroundworkeren.

 

Kode for workeren:

 

        void sender_DoWork(object sender, DoWorkEventArgs e)
       {
           string s = (string)e.Argument;

           try
           {
               byte[] test = new byte[s.Length];
               test = System.Text.Encoding.Default.GetBytes(s.ToString());
               serverTextStream.Write(test, 0, test.Length);
               serverTextStream.Flush();
           }
           catch (IOException ioe)
           {
               MessageBox.Show("Trouble!\r\nCould not send command to DPC\r\n" + ioe.Message);
           }           
       }

 

Forslag, råd og vink mottas med takk...

Lenke til kommentar
Videoannonse
Annonse

BackgroundWorkeren kjører jo i en annen tråd, så du bør ikke vise Messagebox'er eller gjøre annet GUI-ting i DoWork. BackgroundWorker fanger alle exceptions som kastes i DoWork og videreformidler de til riktig tråd i RunWorkerCompleted-eventen.

 

I RunWorkerCompleted bør du sjekke om RunWorkerCompletedEventArgs har en Error. Eksempelet i MSDN for BackgroundWorker viser hvordan du gjør det, http://msdn2.microsoft.com/en-us/library//...oundworker.aspx

Lenke til kommentar
BackgroundWorkeren kjører jo i en annen tråd, så du bør ikke vise Messagebox'er eller gjøre annet GUI-ting i DoWork. BackgroundWorker fanger alle exceptions som kastes i DoWork og videreformidler de til riktig tråd i RunWorkerCompleted-eventen.

 

I RunWorkerCompleted bør du sjekke om RunWorkerCompletedEventArgs har en Error. Eksempelet i MSDN for BackgroundWorker viser hvordan du gjør det, http://msdn2.microsoft.com/en-us/library//...oundworker.aspx

 

Har kikket en del på det eksempelet, ja...

 

Oppdatert kode:

        void sender_DoWork(object sender, DoWorkEventArgs e)
       {
           string s = (string)e.Argument;
           byte [] test = System.Text.Encoding.Default.GetBytes(s.ToString());
           serverTextStream.Write(test, 0, test.Length);
           //serverTextStream.Flush();
           e.Result = "Jalla?" + nl;
       }

       void sender_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
           if (e.Error != null)
           {
               MessageBox.Show(e.Error.Message);
           }
           else if (e.Cancelled)
           {
               // Next, handle the case where the user canceled 
               // the operation.
               // Note that due to a race condition in 
               // the DoWork event handler, the Cancelled
               // flag may not have been set, even though
               // CancelAsync was called.
               SetText("Canceled" + nl);
           }
           else
           {
               // Finally, handle the case where the operation 
               // succeeded.
               SetText(e.Result.ToString());
           }
       }

 

Når jeg stepper igjennom ser jeg at RunWorkerCompleted ikke blir utført når det krasjer. Kan det ha noe å gjøre med at jeg kaller doWork fra Click-eventen til en pictureBox? BGWorkeren er i en annen klasse, burde jeg bruke en delegate?

Lenke til kommentar

Du skal ikke kalle DoWork selv, den skal kalles av BackgroundWorkeren. For å bruke BackgroundWorker skal du hekte DoWork-metoden din til workeren sin DoWork-event.

 

worker.DoWork += DoWorkMetode;
worker.RunWorkerCompleted += CompletedMetode;

Så skal du kalle workeren sin RunWorkerAsync() -- denne vil da starte en ny tråd, i denne tråden vil den kalle på DoWorkMetode. Når denne er ferdig vil RunWorkerCompleted-eventen fyres på tråden som opprinnelig kallte RunWorkerAsync og dette fører til at CompletedMetode kjøres.

 

Altså aldri kalle DoWork selv, men kalle RunWorkerAsync() -- er det det du gjør?

Lenke til kommentar

Jeg bruker RunWorkerASync(), ja. Tror faktisk ikke det går an å kalle DoWork manuelt.

 

En annen ting, skal backgroundworkeren instansieres når jeg trenger den (ved museklikk f.eks), eller skal den opprettes ved programstart?

 

Hmm, tenk tenke, tror svaret er "ved programstart", ellers kan jeg ikke sjekke isBusy...

Endret av Mr Burns
Lenke til kommentar
  • 2 uker senere...

Har laget en slags løsning, men den er litt tvilsom...

 

Jeg oppretter en ny backgroundWorker når det trengs uten å sjekk om det er en "ledig". Mao:

 

string s = command + ":" + value.ToString() + ";";
sender = new BackgroundWorker();
sender.DoWork += new DoWorkEventHandler(sender_DoWork);
sender.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sender_RunWorkerCompleted);
sender.RunWorkerAsync(s);

Istedenfor:

string s = command + ":" + value.ToString() + ";";
while (sender.IsBusy)
{
   Thread.Sleep(100);
}
sender.RunWorkerAsync(s);

 

Selve koden som sender en kommando:

void sender_DoWork(object sender, DoWorkEventArgs e)
{
   string s = (string)e.Argument;
   byte [] test = System.Text.Encoding.Default.GetBytes(s.ToString());
   serverTextStream.Write(test, 0, test.Length);
   //serverTextStream.Flush();
   e.Result = "Sent OK!" + nl;
}

Endret av Mr Burns
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...