Hallo ich habe ein Problem einen Thread korrekt zu terminieren. Folgendes Szenario:
public Form1()
{
InitializeComponent();
this.m_thread = new Thread(new ThreadStart(this.StartMethod));
this.m_aborted = false;
this.m_thread.Start();
}
public void StartMethod()
{
for (int i = 0; i < number; i++)
{
if (this.m_aborted)
{
//do something which is needed when thread terminates
return;
}
this.ComputeSomething(i);
this.Invoke(new UpdateProgressbarDelegate(this.UpdateProgress));
}
}
protected override OnClosing(CancelEventArgs e)
{
this.m_aborted = true;
this.m_thread.Join();
}
Das Problem nun ist das der Join nicht funktioniert. Daher wenn ich die Form schließe, dann wird das OnClosing durchlaufen. Soweit so klar. Danach setze ich das flag das der Thread sich selbst beendet, und Join den Thraed. Der Join klappt aber nicht weil der thread grad dabei ist den Invoke der Progressbar auszuführen, und dort ist das Problem. Wenn ich den Debugger mit Break All anhalte, dann sehe ich im Nebenthread das der Callstack am Invoke steht. Ich kann mir aber so richtig kein Reim drauf machen, warum die MessageQueue dort nicht weiter verarbeitet wird. Weis einer Rat bzw. was ich falsch mache?
Again what learned...
Hallo rollerfreak2,
Weis einer [...] was ich falsch mache?
was du falsch machst, hast du schon schon selbst sehr genau beschrieben. Beide Threads warten aufeinander. Klassischer Deadlock. Im GUI-Thread solltest du sowieso keine blockierenden Aufrufe wie Thread.Join verwenden. Brich stattdessen das Closing ab und feuere ganz am Ende des Threads einen eigenen Event, der das Fenster (erneut) schließt (Control.Invoke nicht) vergessen.
herbivore
Hallo,
da Invoke Deinen nebenläufigen Thread anhält, solange die Oberfläche aktualisiert wird, wäre wahrscheinlich BeginInvoke geeigneter. Dann hast Du auch kein Problem mehr mit einem Deadlock, musst allerdings in UpdateProgress prüfen, ob das Fenster noch existiert oder schon aufgeräumt wurde (IsDisposed).
Danke herbivore,
da war das Denkproblem. Ich setze also im OnClosing das flag und breche das OnClosing mit den Eventargs ab. Danach läuft der Nebenthread weiter und beendet sich dann selbst. Dort muss ich dann einfach via. Control.Invoke das Close separat aufrufen, und dann im OnClosing natürlich nichts mehr tun.
Danke für die schnelle Antwort, ich hoffe mal hab das jetzt korrekt beschrieben.
Again what learned...
Hallo zusammen,
musst allerdings in UpdateProgress prüfen, ob das Fenster noch existiert oder schon aufgeräumt wurde (IsDisposed).
dabei muss man aber - wie bei Synchronisation üblich - höllisch aufpassen: Threading in Fenstern: korrekte Vorgehensweise
herbivore