Laden...

Beim Schließen des Fensters lässt sich dessen Worker-Thread nicht korrekt beenden.

Erstellt von rollerfreak2 vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.343 Views
rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren
Beim Schließen des Fensters lässt sich dessen Worker-Thread nicht korrekt beenden.

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...

49.485 Beiträge seit 2005
vor 13 Jahren

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

U
1.688 Beiträge seit 2007
vor 13 Jahren

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).

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 13 Jahren

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...

49.485 Beiträge seit 2005
vor 13 Jahren

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