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
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
.. 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 - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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... 😦
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.
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
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.
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