Ausnahme beim schließen der Form (thread + aufrufen)
Ich habe gerade angefangen zu lernen, über threads und methodinvoking in c#, aber ich habe ein problem, welches ich nicht finden konnte, die Lösung der.
Machte ich einen basic-C# - form-Programm, das fortlaufend aktualisiert wird und die Anzeige eine Zahl, die durch die Gründung eines thread, und rufen Sie delegieren.
Starten neuen thread auf Form1_load:
private void Form1_Load(object sender, EventArgs e)
{
t = new System.Threading.Thread(DoThisAllTheTime);
t.Start();
}
Public void DoThisAllTheTime (was hält die Aktualisierung der Anzahl) :
public void DoThisAllTheTime()
{
while(true)
{
if (!this.IsDisposed)
{
number += 1;
MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
this.Invoke(yolo);
}
}
}
Wenn ich nun auf das X-button des Formulars bekomme ich folgende exception:
"Eine nicht behandelte Ausnahme des Typs 'System.ObjectDisposedException " ist in System.Windows.Forms.dll
Kann nicht aktualisiert werden ein gelöschtes Objekt'
Während ich tatsächlich überprüfen, ob die form entsorgt wurde oder nicht.
EDIT: ich Hinzugefügt catch (ObjectDisposedException ex -) mit dem code, der das problem behoben.
Arbeiten code:
public void DoThisAllTheTime()
{
while(true)
{
number += 1;
try {
MethodInvoker yolo = delegate() { label1.Text = number.ToString(); };
this.Invoke(yolo);
}
catch (ObjectDisposedException ex)
{
t.Abort();
}
}
}
- Gut, die form bekam entsorgt nach
(!this.IsDisposed)
berechnet wurde, aber bevorthis.Invoke(yolo);
genannt wurde. Willkommen in der Welt der Rennen. - Ich habe deine bearbeiteten Titel. Bitte sehen, "Sollten Fragen enthalten "tags" im Titel?", wo der Konsens ist ", Nein, Sie sollten nicht".
- +1 für die variable yolo
- Wie würde ich das beheben? Ich nahm an, die zu überprüfen wäre schneller als die methodinvoke. Es wird auch verwendet, auf der MSDN-Website, dass Art und Weise. ( msdn.microsoft.com/en-us/library/... )
- Wie andere schon sagten, dies ist ein Rennen-problem siehe: stackoverflow.com/questions/1874728/...
- zählen Sie nicht auf MSDN-Beispielcode, die richtige. In der Regel ist es das nicht.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihren Anruf
this.IsDisposed
ist immer veraltet. Sie müssen zum abfangen von Ihrer form-closing-Ereignis aus und beenden Sie den thread explizit. Dann werden Sie nicht haben zu tun, dassIsDisposed
test überhaupt.Gibt es viele Möglichkeiten, wie Sie dies tun können. Persönlich würde ich die
System.Threading.Tasks
namespace, aber wenn Sie möchten, um Ihre Nutzung derSystem.Threading
sollten Sie definieren eine member-variable_updateThread
, und starten Sie es in Ihrem load-Ereignis:Dann in Ihre Abschlussveranstaltung:
Schließlich, ersetzen Sie den
IsDisposed
test mit überprüfung auf den Wert Ihres neuen_stopCounting
member-variable:t.Join();
zu warten, bis der thread hat erkannt, es.Invoke
blockiert wartet der Haupt-thread, gibt es eine Möglichkeit für einen deadlock, wenn derForm1_Closing
Methode ausgeführt wird auf der Linienumber += 1;
. Die Wahrscheinlichkeit von Deadlocks steigt, da mehr und mehr die Arbeit erfolgt auf der Linie. Ich fixe das in meiner app mitBeginInvoke
stattInvoke
seitBeginInvoke
blockieren nicht den thread beenden und damit denJoin
wird nicht immer blockieren.Nur diese überschreibung in Ihrer form-Klasse:
Thread.Abort()
,Application.Exit()
usw. Ich habe gesehen, dass ein bug verursacht durch das -- Transaktionen nicht zurückgesetzt, weil der eine spuriosEnvironment.Exit()
innerhalb einesOnClose()
event-handler.