AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TThread in Liste sauber aufräumen

Ein Thema von Schwedenbitter · begonnen am 12. Feb 2010 · letzter Beitrag vom 12. Feb 2010
Antwort Antwort
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

TThread in Liste sauber aufräumen

  Alt 12. Feb 2010, 13:22
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
Alex Winzer
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: TThread in Liste sauber aufräumen

  Alt 12. Feb 2010, 15:34
Hallo,

also ich habe jetzt dieses Statement gefunden. Ich habe natürlich gleich versucht, dass auf meine TListBox zu übertragen. Nur leider funktioniert das nicht. Der Destructor des TThread wird (jedenfalls bei mir) nicht aufgerufen, obwohl alle Befehle in Execute abgearbeitet wurden und FreeOnTerminate:=True ist.
Soll das nur daran liegen, dass es keine TObjectList ist?

Ich habe aber gerade eine TListBox gewählt, weil ich während des Programmierens "zum Debuggen" eine Ausgabe sehen will ... Der Code ist jetzt zum Testen anbei.

Ich begreife es einfach nicht!

Gruß, Alex
Angehängte Dateien
Dateityp: zip openthread_p_121.zip (1,9 KB, 6x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: TThread in Liste sauber aufräumen

  Alt 12. Feb 2010, 15:50
1. Du musst den Destructor schon überschreiben.
2. Warum benutzt du eine ThreadList, wenn du
a) diese nur im MainThread verwendest und
b) du sowieso nicht die eigentliche Funktionalität der ThreadList (Methode: LockList) verwendest?


Edit: 2A ist im angehängten Projekt entfallen, da du ja jetzt nicht mehr synchronize verwendest, und damit die ThreadList von beiden Threads benutzt wird --> LockList verwenden.

Edit2: Und außerdem löschst du die Listenelemente gleich zweimal in CleanUp und in FormDestroy.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: TThread in Liste sauber aufräumen

  Alt 12. Feb 2010, 16:16
Hallo Sirius,

Zitat von sirius:
1. Du musst den Destructor schon überschreiben.
Das habe ich zwischenzeitlich schon selbst gemerkt und behoben.

Zitat von sirius:
2a. Warum benutzt du eine ThreadList, wenn du diese nur im MainThread verwendest ...
Es tut mir leid, aber diese Frage verstehe ich nicht?
Mein Fernziel ist es später, das jeder Thread seine eigene Datei überwacht. Es sind Textdateien. In der Textverarbeitung ist Autosave und sonstwas an und wir haben ein sehr langsames VPN. Der Thread soll die Datei nach TEMP kopieren, mit dem verknüpften Programm dort starten und nach dem Ende wieder an den Ursprungsort zurück verfrachten.
-> Ich dachte dafür wäre ein Thread wie geschaffen. Hier teste ich doch nur!

Zitat von sirius:
2b. Warum benutzt du eine ThreadList, wenn du sowieso nicht die eigentliche Funktionalität der ThreadList (Methode: LockList) verwendest?
Das verstehe ich auch nicht. Ich habe nachgelesen und bin zu der Meinung gelangt, dass LockList "nur" dafür sorgt, dass nicht alle gleichzeitig auf die Liste zugreifen können. Ich baue das aber noch ein.

Zitat von sirius:
Edit2: Und außerdem löschst du die Listenelemente gleich zweimal in CleanUp und in FormDestroy.
Das verstehe ich ja auch nicht. Denn das Element müsste in Cleanup gelöscht worden sein. Dann dürfte es aber bei FormDestroy nicht mehr existieren, oder?

Mein Problem ist auch nicht, dass es nicht klappt, sondern die "komische" Fehlermeldung:
Thread-Fehler: Das Handle ist ungültig (6)
Und dass obwohl ich den Code aus meiner Fundstelle bis auf den Thread 1:1 abgeschrieben habe.

[edit]Mit 1:1 abgeschriebenem Code kommt schon beim Anlegen des Thread diese Fehlermeldung:
Exception der Klasse EAbstractError mit der Meldung 'Abstrakter Fehler'.[/edit]

Bitte nicht hauen: Es gibt bei TObjectList die Eigenschaft OwnsObjects. Wenn ich die auf True setze, dann müssten doch die Threads beim Beenden mit platt gemacht werden, oder?

Gruß und Danke, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: TThread in Liste sauber aufräumen

  Alt 12. Feb 2010, 16:32
Zitat von Schwedenbitter:
Es tut mir leid, aber diese Frage verstehe ich nicht?
Mein Fehler: var ThreadList ist ja keine TThreadList, sonder eine TListBox. Dann musst du dringend in TOpenThread.Destroy snychronisieren. Aber Punkt 2 von mir kannst du damit vergessen.

Zitat:
Zitat von sirius:
Edit2: Und außerdem löschst du die Listenelemente gleich zweimal in CleanUp und in FormDestroy.
Das verstehe ich ja auch nicht. Denn das Element müsste in Cleanup gelöscht worden sein. Dann dürfte es aber bei FormDestroy nicht mehr existieren, oder?
FormDestroy ist meist schneller.

Zitat:
Mein Problem ist auch nicht, dass es nicht klappt, sondern die "komische" Fehlermeldung:
Ich wollte erstmal den Thread aufräumen. Dann lösen sich die meisten Probleme von allein.


Zitat:
Bitte nicht hauen: Es gibt bei TObjectList die Eigenschaft OwnsObjects. Wenn ich die auf True setze, dann müssten doch die Threads beim Beenden mit platt gemacht werden, oder?
nö.
Wird nur Free aufgerufen, aber nicht beendet.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:37 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