Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - MessageThread-Berechnung abbrechen
NTcomputer - Do 13.05.10 15:50
Titel: MessageThread-Berechnung abbrechen
Hallo,
ich benutze einen
TMessageThread [
http://www.delphi-library.de/topic_Ereignisorientierte+ThreadsMessage+Handling_90333.html], um CPU-lastige Berechnungen auszuführen, wenn dies erforderlich ist. Jetzt kann es aber passieren, dass die aktuelle Berechnung "verworfen" werden soll, um sofort eine neue zu starten.
Meine Frage dazu ist: Wie lässt sich die derzeitige Aktion des TMessageThread SOFORT abbrechen, um gleich danach beispielsweise eine OnTerminate-Funktion aufzurufen, in der alle Variablen sauber freigegeben werden? Ich meine damit einen Befehl von außen (vom startenden Thread), nicht innerhalb des berechnenden Threads selbst, da die Berechnungen teilweise sehr lange dauern bzw. der Aufwand zu groß wäre, jedesmal auf eine Variable (Terminated) zu überprüfen. Ein Kill durch die API-Funktion TerminateThread wäre ungünstig, da sonst große Mengen nicht freigegebener Variablen im Arbeitsspeicher liegen bleiben.
Ich hoffe ihr könnt mir weiterhelfen, habe bisher noch nichts dazu passendes gefunden.
Moderiert von
Narses: Link URL-codiert.
jaenicke - Do 13.05.10 16:39
Es gibt keine andere Möglichkeit. Ein Thread kann ausschließlich im Thread selbst abgebrochen werden. Eben wie du sagtest über Terminated.
Denn wenn ein Thread von außen abgebrochen würde, wäre der Zustand darin zu dem Zeitpunkt undefiniert. Deshalb geht das nicht. Dazu kommt noch die Freigabe der Objekte usw.
Eine einfache Prüfung auf einen Abbruch dauert eigentlich auch nicht so lange, sollte aber natürlich wenn möglich nur von Zeit zu Zeit passieren.
NTcomputer - Fr 14.05.10 10:01
Danke, dann weiß ich zumindest mit Sicherheit dass so wie ich mir das vorgestellt habe nicht geht.
Werde ich wohl oder übel im Thread selbst auf Terminated prüfen, auch wenn das einige Zeit dauern kann (nicht die Prüfung selbst, sondern die Berechnungen, die vor jeder Prüfung kommen).
jaenicke - Fr 14.05.10 21:06
Du kannst aber die Priorität des abzubrechenden Threads herabsetzen. Dann wird zuerst der aktuelle Thread ausgeführt und die abzubrechenden Threads erst, wenn wieder Rechenzeit zur Verfügung steht.
Dabei musst du natürlich schauen, dass da nicht zu viele Threads parallel abzubrechen sind irgendwann, aber auf diese Weise kannst du die Folgen des verzögerten Abbruchs auf die aktuellen Berechnungen mildern.
delfiphan - Sa 15.05.10 23:38
Geht so weit ich weiss nicht (in .NET schon).
Wenn man eine Exception in einem anderen Thread raisen könnte hättest du immer noch Probleme beim Freigeben von Speicher.
Denn wenn du sowas hast:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| ABC := TABC.Create; try finally ABC.Free; end; |
Man geht hier davon aus, dass zwischen Create und try keine Exceptions geworfen werden. Dies wäre nicht garantiert, wenn man von einem anderen Thread aus einfach mal eine Exception in einen anderen Thread injecten könnte.
Statt auf Terminated zu prüfen könntest du theoretisch auch Speicher überschreiben und so einen Jump-Befehl "injecten". Aber sauber ist das natürlich nicht.
TerminateThread könntest du verwenden, wenn du in einem Thread nur Harmloses machst (was vermutlich eher nicht der Fall ist), d.h. wenn du alle Objekte auf dem Stack allokierst, keine Win32-Handles hast, keine CriticalSection verwendest, keine Kernel-Code ausführst usw. verwendest. Wohl eher nicht der Fall.
Oder du machst eine Multi-Prozess Architektur. Dann könntest du den Prozess abschiessen. Du kannst über Shared Memory Speicher austauschen, Messages verschicken und Semaphores verwenden.
NTcomputer - So 16.05.10 13:05
Danke euch für die ganzen Tipps.
@jaenicke: Das geht bei meiner Anwendung nicht, da ich ja nicht die Rechenzeit für den anderen Thread brauche, sondern im Gegenteil der Thread so schnell wie möglich abgebrochen werden soll (also Berechnungen eher schneller abschließen), weil er sofort neue Aufgaben bekommt.
@delfiphan: An das mit der Exception hatte ich auch schon gedacht, nur bekomme ich dann unter Umständen Probleme mit der Synchronisierung beim Freigeben (die benutzen Variablen werden auch von anderen Threads verwendet).
Und es ging mir ja wiegesagt um eine "saubere" Lösung.
Die Multi-Prozess-Idee ist eigentlich geeignet, nur kommt dazu dann der Mehraufwand der Verwaltung.
Ich denke, ich bleibe bei der Variablenprüfung innerhalb des Threads. Muss der Nutzer halt bisschen länger warten ;-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!