Laden...

String wird im BackgroundWorker nicht aktualisiert? [=> doch, gleich mehrfach aktualisiert]

Erstellt von Chester vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.725 Views
Thema geschlossen
C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren
String wird im BackgroundWorker nicht aktualisiert? [=> doch, gleich mehrfach aktualisiert]

Hallo,
Ich bin gerade ziemlich frustriert, da ein String sich in einem BackgroundWorker einfach nicht aktualisieren will, bzw. nicht aktualisiert ausgegeben wird... Das komische ist, dass nur dieses "else if" betroffen ist, alle anderen funktionieren ganz normal...


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
	for (int i = (StartNumber - 1); i < cDb.Length; i++)
                {
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }
					
					status = "Trying " + (i + 1).ToString() + " of " + cDb.Length.ToString();
                    progress += (int)0.1;
                    backgroundWorker1.ReportProgress(progress);


                    Thread.Sleep(IntervalInt / 2);
                    mcc.SendChat(cDb[i]);
                    Thread.Sleep(IntervalInt / 2);

                    int waitingtime = 0;
                    while (stopBool)
                    {
                        if (backgroundWorker1.CancellationPending)
                        {
                            e.Cancel = true;
                            break;
                        }
                        Thread.Sleep(5);
                        waitingtime += 5;
                    }
                    stopBool = true;

                    if (waitingtime > 3000)
                    {
                        status = "\nConnection timeout: more than 3000ms.\nDisconnecting...\nDisconnected.";
                        StatusLabel1 = "Done.";
                        progress += (int)0.1;
                        backgroundWorker1.ReportProgress(progress);
                        working = false;
                        backgroundWorker1.CancelAsync();
                    }
                    else if (recMessage == "\"test message\"")
                    {
                        status = "negative"; //<-- Hier setze ich den String auf "negative", doch wenn ich den Progress reporte, kommt immernoch "Trying [...]" von weiter oben an... :(
                        progress += (int)0.1;
                        backgroundWorker1.ReportProgress(progress);
                    }
                    else
                    {
                        status = "\nUnknown response: " + recMessage;
                        progress += (int)0.1;
                        backgroundWorker1.ReportProgress(progress);
                    }
                }
}		

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            logbox.Text += status; //<-- Hier stellt es den "Trying [...]"-String rein, obwohl der String eigentlich schon aktualisiert wurde auf "negative"... :/
            StartNumberTextBox.Text = StartNumber.ToString();
            logbox.SelectionLength = 0;
            logbox.SelectionStart = logbox.Text.Length;
            logbox.ScrollToCaret();
        }

(Den Code habe ich deutlich gekürzt)

Ich hoffe, jemand kann mir helfen,

Gruß,
Chester

5.658 Beiträge seit 2006
vor 10 Jahren

Hi Chester,

  
progress += (int)0.1;  
   

Was möchtest du mit dieser Anweisung erreichen?

  
logbox.Text += status; //<-- Hier stellt es den "Trying [...]"-String rein, obwohl der String eigentlich schon aktualisiert wurde auf "negative"... :/  
   
  

Er "stellt" den String nicht "rein", sondern hängt ihn an den aktuellen Text an (+= Operator).

Ansonsten empfehle ich dir, deine Anwendungen zu testen und debuggen. Damit sollte sich die Fehlerquelle sehr schnell auffinden lassen.

Christian

Weeks of programming can save you hours of planning

16.827 Beiträge seit 2008
vor 10 Jahren

.. und mal die Grundlagen von Multithreading, GUI-Aktualisierungen durch Threads und auch die C# Basics bezüglich Events anzuschauen. Das tut ja weh in den Augen (sorry 😉

C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren

Mit progress += (int)0.1; möchte ich erreichen, dass sich der progress des backgroundWorkers erhöht, um das ProgressChanged-Event aufzurufen.
Der Text wird angehängt, da es eine logbox ist, soll heißen, es wird alles aufgeschrieben was passiert, meistens so: "\nTesteintrag". Nur dieses eine Mal habe ich keine neue Zeile angefangen, sondern möchte es an die aktuelle Zeile dranhängen, nur es doppelt die vorherige Zeile mit "Trying [...]"...

Mit dem Debugger hab ich schon herausgefunden, dass die Variable 'status' "negative" tatsächlich enthält, es postet jedoch trotzdem den vorher enthaltenen String... 😦

Hinweis von herbivore vor 10 Jahren

Bitte keine weitere Diskussion zu progress += (int)0.1. Die Anweisung ist Unsinn, weil (int)0.1 echt 0 ist und daher progress nicht erhöht wird. Das sind aber Grundlagen, siehe [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren

Okay, ich habe jetzt herausgefunden, dass es daran liegt: Alle anderem Fälle beenden den backgroundWorker (habe es außerdem auch auch switch() umgestellt):
z.B:


case ("\"Username not registered\""):
                            {
                                status = "\nError: Username not registered.\n(Probably you misspelled the username?)";
                                Thread.Sleep(100);
                                status += "\nDisconnecting...\nDisconnected.";

                                backgroundWorker1.ReportProgress(progress);
                                working = false; //Sagt dem Worker, nicht neustarten
                                backgroundWorker1.CancelAsync(); //Beendet ihn
                            }
                            break;

                        case ("\"Wrong password\""):
                            {
                                status = "negative";
                                Thread.Sleep(100);

                                backgroundWorker1.ReportProgress(progress);
                                //Wenn ich hier auch den Worker abbreche, funktioniert das ganze... :/
                            }
                            break;
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (working)
            {
                progress = 0;
                Thread.Sleep(3000);
                backgroundWorker1.RunWorkerAsync();
            }
            else
            {
                Thread.Sleep(1000);
                mcc.Client.Close();
                StartButton.Text = "Start!";
            }
        }

Hat jemand eine Idee, woran es liegt?

Gruß,
Chester

849 Beiträge seit 2006
vor 10 Jahren

Du führst das ganze in einer schleife aus.

Soweit ich weis wird das event ProgressChanged mit dem Gui Thread gesynct und asyncron ausgeführt das braucht Zeit.

Das heisst wenn ProgressChanged wirklich gefeuert wird, ist deine schleife schon im nächsten durchlauf und hat den String schon wieder auf Trying gesetzt (vllt. sogar schon mehrmals).

So etwas nennt sich Race Condition.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Chester,

richtig, ProgressChanged delegiert asynchron an den GUI-Thread. ReportProgress benutzt dazu die SynchronizationContext.Post-Methode (und eben nicht Send).

Abhilfe schafft die direkte Benutzung von SynchronizationContext.Send oder eben Control.Invoke (und nicht Control.BeginInvoke).

Damit sind wir dann aber bei [FAQ] Wie finde ich den Einstieg in C#? und die FAQ ist so gereift und vollständig ist, dass sich daraus alles weitere ergibt.

Oder du benutzt gleich BackgroundWorker.ReportProgress Method (Int32 percentProgress, Object userState) und übergibst die den String als userState.

herbivore

Thema geschlossen