Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Thread killen (https://www.delphipraxis.net/68286-thread-killen.html)

_frank_ 27. Apr 2006 12:34


Thread killen
 
hi,
bei der Entwicklung meines DFM_Editors musste ich festellen, das die ObjectBinaryToText-Funktion von Delphi 3 bei binären Delphi 7-Formularen (als Resource in exe/dll) manchmal in einer Endlosschleife festhängt:

procedure ConvertProperty
procedure convertValue
while not Reader.EndOfList do
begin
NewLine;
ConvertValue;
end;

Also hab ich mir gedacht, diesen code in einen Thread auszulagern, um ihn bei bedarf beenden zu können.

im TThread.execute mache ich nur das ObjectBinaryToText, und setze ein flag für waitforsingleobject (welche nach dem terminate noch 10 sek wartet bevor der thread hard gekillt wird)

der thread wird erzeugt und das terminate-event zu gewiesen:
Delphi-Quellcode:
procedure TForm_ChooseRes.ThreadTerminate(Sender: TObject);
begin
//Sender.Free;
convThread:=nil;
threadDone:=True;
Btn_StartThread.Enabled:=true;
Btn_StopThread.enabled:=false;
end;

convThread:=TConvertThread.create;
convThread.OnTerminate:=ThreadTerminate;
ThreadKilled:=false;

der thread wird so gestartet (suspended):

convThread.SetStreams(rs,ms); //die zu verarbeitenden Streams übergeben
convThread.setMethod(cmBinToTxt);
ResetEvent(hEvent);//flag für waitforsingleobject
convThread.resume;Thread starten
threadDone:=false;
while not (threadDone or ThreadKilled) do
application.ProcessMessages; //einfrieren der GUI verhindern
if not ThreadKilled then
begin
ms.position:=0;
s.LoadFromStream(Ms);
end;

und so versuche ich ihn zu beenden:

if assigned(convThread) then
begin
id:=convThread.ThreadID;
convThread.terminate;
res:=waitforsingleObject(hEvent,10000);
if res=WAIT_TIMEOUT then
begin
terminateThread(ID,0);
ThreadKilled:=true;
end;
end;
wenn der thread gekillt wird, bekomme ich eine external Exception (Zugriffsverletzung). ich kann mir nur nicht erklären, woran das liegt.

den kompletten source gibts unter:
www.fw-web.de/download/d....9.1_testing_src.zip
der thread ist in der thread_convert.pas definiert

Hoffe, ihr könnt mir helfen.

Gruß Frank

[edit=SirThornberry]Delphi-Tags gesetzt Mfg, SirThornberry[/edit]

shmia 27. Apr 2006 14:15

Re: Thread killen
 
Der Thread ist selbst dafür verantwortlich, zu erkennen, dass er beendet wurde.
Also muss innerhalb der Schleifen das Property Terminated abgefragt werden:
Delphi-Quellcode:
while (not Reader.EndOfList) and (not Terminated) do
begin
   // arbeiten
end;
Man muss auch nicht in jeder Schleife dieses Property Terminated abfragen.
Es reicht, wenn dies an strategisch günstigen Stellen eingebaut wird.
Beispiel:
der Thread soll ein Bild mit 1000 * 1000 Pixeln errechnen.
Man braucht nun nicht bei jedem Pixel prüfen, ob der Thread terminiert wurde;
er reicht aus, dies bei jeder neuen Bildzeile zu tun.

_frank_ 27. Apr 2006 14:29

Re: Thread killen
 
wenn das ginge würde ich es machen...
leider geht dieses Abfragen des Flags nicht, da ich in dem Thread nur die Delphi-Funktion aufrufe, diese selber hängt.
Wäre es nicht ein OS-Projekt könnte ich die Sources verwenden um mir ne eigene Funktion zu basteln um darin das flag zu prüfen, aber das würde sicherlich gegen Copyrights verstoßen

Gruß Frank

shmia 27. Apr 2006 16:51

Re: Thread killen
 
Zitat:

Zitat von _frank_
wenn das ginge würde ich es machen...
leider geht dieses Abfragen des Flags nicht, da ich in dem Thread nur die Delphi-Funktion aufrufe, diese selber hängt.

Ist soweit jetzt klar; also musst du "Gewalt" anwenden.
Delphi-Quellcode:
 // Achtung: TerminateThread möchte das Hanlde nicht die ID des Threads
 if not TerminateThread(convThread.Handle, 99) then
    // bei Fehler eine Exception auslösen
    // die Message könnte zur Problemlösung beitragen
    RaiseLastWin32Error;
  convThread.Free;

_frank_ 27. Apr 2006 17:04

Re: Thread killen
 
gut, zugriffsverletzung ist jetzt nicht mehr, jedoch hängt jetzt das Programm beim versuch den MemoryStream freizugeben, den ich dem thread zum verarbeiten mitgegeben habe...vermutlich ist der thread noch nicht gekillt. Es wird kein Fehler ausgespuckt (LastWin32Error).

ich benutze deshalb die refernzen auf die streams, weil im Falle des Abschießens ja der Speicher nicht freigegeben wird, den der Thread belegt.
Sonst hätte ich im thread eigene Streams verwendet und per assign oder write kopiert.

shmia 27. Apr 2006 17:36

Re: Thread killen
 
Tja, nun kommt der harte Kampf mit dem Debugger (bei Threads besonders schwierig)
Vielleicht hilft dir das etwas weiter:
http://www.delphipraxis.net/download.php?id=7572

_frank_ 27. Apr 2006 20:11

Re: Thread killen
 
bringt leider auch nix, weder debugview (zeigt nix an) noch assert (Pointer gültig) bringt mich weiter, der thread taucht noch nicht mal im Thread-Fenster der IDE auf

kann es sein, dass der thread die 2 Stream-pointer sperrt, so dass ich die nicht freigeben kann?
wie kann man das umgehen?

Gruß Frank


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz