Hallo,
ich möchte ein Programm schreiben, in dem Dateien per Thread überwacht werden.
(Dazu gibt es ja schon etliche Theme ebenso wie zur Verwaltung von Thread. Aber daraus bin ich nicht wirklich schlau geworden.) Momentan wird nur hochgezählt. Den Dateinamen schreibe ich in eine Liste. Es ist
FreeOnTerminate:=True gesetzt, so dass ich mich um das aufräumen nicht mehr kümmern muss. Am Ende von
Excute rufe ich dann (Synchronized) eine Procedure auf, in der noch der Listeneintrag gelöscht wird. Läuft der Thread komplett durch,
ist alles OK.
Ich habe aber ein Problem, wenn ich das Programm vorher beende. In
OnCloseQuery gehe ich die Liste durch und rufe die
Procedure Terminate auf und Lösche den Listeneintrag. Jetzt habe ich ein Speicherleck (gemäß Meldung von FastMM4.94). Wenn ich zusätzlich noch .Free aufrufe, dann bekomme ich eine
Exception:
Delphi-Quellcode:
Type
TOpenThread = Class(TThread)
Public
FileName : String;
Protected
TFCount : Int64;
Procedure Progress;
Procedure Execute; Override;
Procedure CleanUp;
End;
TForm1 = Class(TForm)
ThreadList : TListBox;
BtnStart : TButton;
ODiag : TOpenDialog;
Procedure BtnStartClick(Sender: TObject);
Procedure FormCloseQuery(Sender: TObject; Var CanClose: Boolean);
End;
...
Procedure TOpenThread.Progress;
Var
I : Integer;
Begin
I:=Form1.ThreadList.Items.IndexOfObject(self);
Form1.ThreadList.Items.Strings[I]:=FileName + ' ' +FormatFloat('0,', TFCount);
End;
Procedure TOpenThread.Execute;
Var
I : Integer;
Begin
I:=0;
While (Not Terminated) And (I < 150000) Do
Begin
Inc(I);
TFCount:=I;
Synchronize(Progress);
End;
Synchronize(CleanUp);
End;
Procedure TOpenThread.CleanUp;
Var
I : Integer;
Begin
I:=Form1.ThreadList.Items.IndexOfObject(self);
Form1.ThreadList.Items.Delete(I);
End;
Procedure TForm1.BtnStartClick(Sender: TObject);
Var
OThread : TOpenThread;
Begin
If ODiag.Execute Then
Begin
OThread:=TOpenThread.Create(True);
OThread.FreeOnTerminate:=True;
OThread.FileName:=ODiag.FileName;
OThread.Priority:=tpIdle;
ThreadList.AddItem(ODiag.FileName, OThread);
OThread.Resume;
End;
End;
Procedure TForm1.FormCloseQuery(Sender: TObject; Var CanClose: Boolean);
Begin
If ThreadList.Count = 0 Then
CanClose:=True
Else
If MessageBox(0, 'Sollen noch laufende Threads beendet werden?',
'Sicherheitsabfrage', mb_YESNO Or mb_IconQuestion) = idYES Then
Begin
While ThreadList.Count > 0 Do
Begin
TOpenThread(ThreadList.Items.Objects[0]).Terminate;
// TOpenThread(ThreadList.Items.Objects[0]).WaitFor;
// TOpenThread(ThreadList.Items.Objects[0]).Free;
ThreadList.Items.Delete(0);
End;
CanClose:=True;
End
Else
CanClose:=False;
End;
End.
Wo liegt hier mein Fehler?
Gruß, Alex