Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

String wird im BackgroundWorker nicht aktualisiert? [=> doch, gleich mehrfach aktualisiert]
Chester
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

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

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5988
Herkunft: Leipzig

beantworten | zitieren | melden

Hi Chester,
Zitat von Chester


progress += (int)0.1;
 

Was möchtest du mit dieser Anweisung erreichen?


Zitat von Chester


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
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16145

beantworten | zitieren | melden

.. 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 ;-)
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Chester
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

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... :(
private Nachricht | Beiträge des Benutzers

Moderationshinweis von herbivore (04.07.2013 - 20:19:16):

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.

Chester
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers