2008-10-31 5 views
5

Ich habe ein Threading-Problem mit Delphi. Ich denke, das ist auch in anderen Sprachen üblich. Ich habe einen langen Prozess, den ich in einem Thread mache, der eine Liste im Hauptfenster ausfüllt. Aber wenn sich einige Parameter in der Zwischenzeit ändern, sollte ich den laufenden Thread stoppen und von vorne anfangen. Delphi schlägt vor, einen Thread zu beenden, indem Sie Terminated: = true festlegen und im Thread auf den Wert dieser Variablen prüfen. Mein Problem ist jedoch, dass der lange Ausführungsteil in einem Bibliotheksaufruf vergraben ist und ich in diesem Aufruf nicht nach der Terminierten Variable suchen kann. Daher musste ich warten, bis dieser Bibliotheks-Aufruf beendet war, was sich auf das gesamte Programm auswirkt.Wie kann man das lange Ausführen von Threads sauber stoppen?

Was ist der bevorzugte Weg in diesem Fall? Kann ich den Thread sofort töten?

+1

Was ist der lange laufende Bibliotheksaufruf? –

Antwort

3

Die Threads müssen zusammenarbeiten, um ein ordnungsgemäßes Herunterfahren zu erreichen. Ich bin mir nicht sicher, ob Delphi einen Mechanismus zum Abbrechen eines anderen Threads bietet, aber solche Mechanismen sind in .NET und Java verfügbar, sollten aber als eine Option des letzten Ausweges betrachtet werden, und der Zustand der Anwendung ist nach ihrer Verwendung unbestimmt.

Wenn Sie einen Thread an einem beliebigen Punkt beenden können, können Sie ihn töten, während er eine Sperre im Speicherzuordner hält (zum Beispiel). Dadurch bleibt Ihr Programm geöffnet, wenn Ihr Haupt-Thread als nächstes auf diese Sperre zugreifen muss.

9

Der bevorzugte Weg besteht darin, den Code so zu modifizieren, dass er nicht blockiert, ohne die Löschung zu überprüfen.

Da Sie den Code nicht ändern können, können Sie das nicht tun; Sie müssen entweder mit der Hintergrundoperation leben (aber Sie können sie von jeder Benutzerschnittstelle trennen, so dass ihre Fertigstellung ignoriert wird); oder alternativ können Sie versuchen, es zu beenden (TerminateThread API wird jeden Thread mit seinem Handle grob beenden). Die Terminierung ist nicht sauber, obwohl, wie Rob sagt, alle vom Thread gehaltenen Sperren verworfen werden und jeder durch solche Sperren geschützte Cross-Thread-Status sich möglicherweise in einem beschädigten Zustand befindet.

Können Sie erwägen, die Funktion in einer separaten ausführbaren Datei aufzurufen? Vielleicht mit RPC (Pipes, TCP, anstatt Shared Memory aufgrund der gleichen Sperre Problem), so dass Sie einen Prozess beenden können, anstatt einen Thread zu beenden? Die Prozessisolierung wird Ihnen viel mehr Schutz bieten. Solange du dich nicht auf prozessübergreifende Dinge wie Mutexe verlässt, sollte es viel sicherer sein, als einen Thread zu töten.

+0

Das klingt wie ein guter Rat.Wenn Sie diesen Anruf in einem anderen Prozess tätigen, hinterlassen Sie keine Spuren, nachdem Sie ihn verloren haben. – Glenner003

3

Wenn Sie den Code nicht ändern können, um nach Beendigung zu suchen, legen Sie seine Priorität wirklich niedrig fest und ignorieren Sie sie, wenn sie zurückkehrt.

0

Ich schrieb dies in ihrer Antwort auf eine similar question:

Ich verwende eine ausnahmebasierte Technik , die in einer Anzahl von Win32-Anwendungen für mich ziemlich gut gearbeitet hat.

Um einen Thread zu beenden, verwende ich QueueUserAPC, um einen Aufruf an eine -Funktion, die eine Ausnahme auslöst, in die Warteschlange. Die Ausnahme, die ausgelöst wird ist nicht vom Typ "Exception" abgeleitet, so wird nur von Wrapper-Prozedur meines Threads abgefangen werden.

Ich habe dies sehr erfolgreich mit C++ Builder-Anwendungen verwendet. Mir sind nicht alle Feinheiten der Exception-Behandlung von Delphi gegen C++ bekannt, aber ich würde erwarten, dass sie leicht geändert werden kann, um zu funktionieren.

Verwandte Themen