Laden...

Threads mit Form Close beenden?

Erstellt von HolySheepy vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.883 Views
H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren
Threads mit Form Close beenden?

Hi,

ich habe jetzt 2 Threads offen die in einer Schleife laufen

while(ThreadRun == true )

vor der while schleife geben sie aus das sie sich gestarter haben und nach der while schleife das sie nun beendet sind.
Das funktioniert nun auch ganz gut.

Ich benutze nun aber einen 3ten Thread der ThreadRuna auf true setzt und bei beiden überprüft ob IsAlive true ist und denen .Join()'ed wenn sie es sind und danach auch ausgibt das er fertig ist. Funktioniert soweit auch.

Problem jetzt, wenn man nich einfach auf den "Stop" Button klickt sondern auf das X muss er die Threads und so ja auch beenden, also hab ich bei Form1_Closed gemacht das er die Funktion aufruft die den Stop Thread startet.

Nun funktioniert die Ausgabe aber auch manchmal nichtmehr( über Invoke und dann in ein Textfenster in der Form reingeschrieben), da das Form schon disposed wurde. Tja, und dann hängt er bei der Ausgabe und beendet sich selbst nicht(der Thread der darauf wartet das die anderen beiden stoppen)...

Wie löse ich das nun?

3.971 Beiträge seit 2006
vor 15 Jahren

Schalte eine transparente Ausgabe-Klasse dazwischen. Diese Regelt die Ausgabe und prüft vorher ob das Form bereits Disposed ist. Weiterer Vorteil, du kannst die Ausgabe-Klasse zu einem späteren Punkt überschreiben und so nicht mehr auf einen WinForm sondern zum Beispiel das ganze auf der Console ausgeben lassen, oder auf einen entfernten Rechner

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

nuja eigentlich hatte ich auf isdisposed geprüft, lustig war im Debugger dann nur das er bei dem Invoke befehl die Exception angezeigt hatte das es schon Disposed ist aber als ich bei der if direkt obendrüber die Bedingungen kontrolliert habe hätte der Befehl nichtmal ausgeführt werden dürfen....

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

habs mal so probiert mias ausgabe klasse

Auschnitt daraus:

            if( this.mainForm.IsDisposed == false )
                {
                Tools.Msg.Add( "lpm" );
                if( this.mainForm.InvokeRequired == true )
                    {
                    Tools.Msg.Add( this.mainForm.IsDisposed.ToString() + " // " + "lml" );
                    this.mainForm.Invoke( new fAddNewMessage( this.mainForm.newMessage ), new object[] { (object)msg } );

                    }
                else
                    {
                    this.mainForm.newMessage( msg );
                    }
                }

der CloseThread gibt vor dem aufrufen aus
Close Thread Closing....
und sollte danach ausgeben
Close Thead Closed...

nur dazu klommts nie
nach
False // lml erfolgt keine Ausgabe mehr, der Prozess ist aber noch Offen, das Form jedoch geschlossen

3.971 Beiträge seit 2006
vor 15 Jahren

Wenn das Form bereits geschlossen ist, ist es nicht möglich dort was anzuzeigen. Sollte ein Fehler allerdings anschließend auftreten (ObjectDisposedException) fangen und ignorieren

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

Ja aber ich check ja vorher obs disposed ist? Also wundert mich das etwas...

edit:

            if( this.mainForm.IsDisposed == false )
                {
                Tools.Msg.Add( "lpm" );
                if( this.mainForm.InvokeRequired == true )
                    {
                    Tools.Msg.Add( this.mainForm.IsDisposed.ToString() + " // " + "lml" );
                    try
                        {
                        Tools.Msg.Add( "message-text" );
                        this.mainForm.Invoke( new fAddNewMessage( this.mainForm.newMessage ), new object[] { (object)msg } );
                        Tools.Msg.Add( "message-textt" );
                        }
                    catch( ObjectDisposedException ex )
                        {
                        Tools.Msg.Err( "error-test-text" );
                        }
                    Tools.Msg.Add( "lllll-message" );
                    }
                else
                    {
                    this.mainForm.newMessage( msg );
                    }

so er sagt nun message-text aber kein message-textt, sowie kein error-text-text
folglich tritt keine exception auf?

edit2:

auch wenn ich nur eine normale Exception nehme tritt keine auf, die funktion die mit dem Invoke aufgerufen wird wird auch nicht ausgelöst

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

so habs nochmal extra getestet, da es mich sehr verwundert

wenn ich es im visual studio mit debugger starte klappt alles wunderbar, auch die nachricht die kommt nachdem er das mit dem output aufruft kommt und so
aber ohne debugger gehts nicht

3.971 Beiträge seit 2006
vor 15 Jahren

Das Problem ist, wenn mehrere Threads ausgeführt werden, dass dein Programm parallel läuft, dabei jeder Thread nur eine bestimmte Ausführszeit zugewiesen (pseudoparallel), oder die Threads laufen richtig parallel auf 2 getrennten Prozessoren.

Fragst du in einem Thread den zustand eines Objekts ab, kann in der selben Zeit, wo die If-Anweisung noch am werkeln ist, das Objekt durch einen Thread geändert werden. Deshalb funktioniert dein Code nicht.

Richtig wäre, das Objekt auf den die Threads zugreifen zu locken (eine Sperre setzen). Dazu gibt es verschiedene Möglichkeiten: lock, Monitor, Waithandle und Mutex

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

hm habs mal mit locks auf das Form versehen, ändert aber nichts
bleibt immernoch stehen wenn er das Invoke aufruft

3.971 Beiträge seit 2006
vor 15 Jahren

Ja, du musst auch den anderen Thread locken. Einseitige Objektsperren gibt es nicht. Locking setzt je nach Anwendungsfall und Implementierung bestimtme Regeln voraus, die von jedem Thread eingehalten werden müssen. Zum nachlesen: MSDN: Threadsynchronisierung (C#-Programmierhandbuch)

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

H
HolySheepy Themenstarter:in
44 Beiträge seit 2006
vor 15 Jahren

hm?
Der Thread ruft die Funktion einer Output Klasse auf und dort mach ich das lock 😠
Laut meinen Tests funktioniert das, habe nämlich mal probiert einfach 3 Threads zu machen dei alle die Klasse aufrufen mit dem lock und so...

Wenn ich bei einem ne Dauerschleife reingemacht habe(so das er immer das lock belegt) konnten die beiden anderen nichtsmehr schreiben, hab ichs so gemacht das er das lock immer zwischendurch freigibt konnten die beiden anderen auch schreiben...

edit:

und damit haben sie ja ein gemeinsames lock objekt: die klasseninstanz vom form1

3.971 Beiträge seit 2006
vor 15 Jahren

Du vergisst das die Gui selbst auch einen Thread hat und so wie es sich anhört lockst du diesen nicht. Hänge dich in Form-Closing und locke auch dort deine Form.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...