| Autor |
Beitrag |
Geri
      
Beiträge: 78
XP
RAD Studio XE pro
|
Verfasst: Sa 02.07.11 07:51
Hallo zusammen
Ich habe eine Anwendung mit einer Thread. Trotz erfolgreichem Aufruf von Terminate erhalte ich mit memchk am Ende eine Meldung, dass die Thread 68 byte nicht freigegeben hat. Ich habe mal ein ganz kurzes Programm geschrieben, bei dem das Problem immer noch auftaucht. Es hat zwei Buttons. Einen um den Thread zu starten, einen um ihn vorzeigig zu beenden. Nach Beendigung der Thread wird zusätzlich ein Event onTerminate aufgerufen. Diese Methode wird auch wirklich aufgerufen. Ich habe mit Delphi 2007 und Delphi XE probiert.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100:
| unit uTestManCursor;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) btnCreate: TButton; btnTerminate: TButton; Memo1: TMemo; procedure btnCreateClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure btnTerminateClick(Sender: TObject); private public FThread:TThread; procedure EnableButtons(); procedure OnTerminate(Sender: TObject); end;
TMyThread=class(TThread) private FTimeToWork:integer; protected procedure Execute;override; public constructor Create(TimeToWork:integer); end;
var Form1: TForm1;
implementation
{$R *.dfm}
constructor TMyThread.Create(TimeToWork: integer); begin FTimeToWork:=TimeToWork; inherited Create(True); end;
procedure TMyThread.Execute; var T:Integer; begin t:=FTimeToWork; Form1.Memo1.Lines.Add('Begin execution'); while not Terminated and (t>0) do begin Form1.Memo1.Lines.Add(format('Remaining %5.2f%%',[t/FTimeToWork*100])); Sleep(500); dec(t,500); end; if Terminated then Form1.Memo1.Lines.Add('Terminated by user'); Form1.Memo1.Lines.Add('Finish execution'); end;
procedure TForm1.EnableButtons(); begin btnCreate.Enabled:=not Assigned(FThread); btnTerminate.Enabled:= Assigned(FThread); end;
procedure TForm1.btnCreateClick(Sender: TObject); begin FThread:=TMyThread.Create(5000); FThread.OnTerminate:=OnTerminate; EnableButtons(); FThread.Resume; end;
procedure TForm1.FormShow(Sender: TObject); begin EnableButtons; end;
procedure TForm1.btnTerminateClick(Sender: TObject); begin FThread.Terminate; end;
procedure TForm1.OnTerminate(Sender: TObject); begin FThread:=nil; EnableButtons(); end;
end. |
Habt ihr vielleicht eine Idee, wo hier das Problem liegen könnte? Memchk als auch die bei Delphi eingebaute Speicherübewachung liefern die Meldung eines Lecks.
Danke für euere Hilfe und beste Grüsse
Geri
|
|
haentschman
      
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Sa 02.07.11 08:33
Guten Morgen...
Delphi-Quelltext 1: 2: 3:
| if Terminated then Form1.Memo1.Lines.Add('Terminated by user'); Form1.Memo1.Lines.Add('Finish execution'); |
- du greifst aus dem Thread heraus auf dein Form1 zu. Das geht nicht gut. Stichwort: Synchronize
Ein Prinzipbeispiel mit freunlichen Grüßen von der DP... wenn sie den Diebstahl bemerkt haben...
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| type MeinForm = class(TMeinForm) lblThreadText: TLabel; private procedure StarteDenThread; end;
type Thread = class(TThread) private Form: TMeinForm; procedure MachVCLSachen; protected procedure Execute; override; public constructor Create(Form: TMeinForm); end;
procedure MeinForm.StarteDenThread; begin Thread.Create(Self); end;
constructor Thread.Create(Form: TMeinForm); begin inherited Create(False); Self.Form := Form; end;
procedure Thread.Execute; begin Synchronize(MachVCLSachen); end;
procedure Thread.MachVCLSachen; begin Form.lblThreadText := 'Der Thread lässt grüßen!'; end; |
PS: Ich denke, daß Deutsch nicht deine Muttersprache ist. Du kannst auch in Englisch schreiben wenn es für dich einfacher ist.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Sa 02.07.11 08:59
haentschman hat folgendes geschrieben : | | PS: Ich denke, daß Deutsch nicht deine Muttersprache ist. |
Sagst du das zu jedem Österreicher  ? Ich würde mit solchen Vermutungen vorsichtig sein, nur weil in einem sonst nicht zu beanstandenen Text jemand den Genus von "Thread" anders gewählt hat, als du es tun würdest  .
_________________ >λ=
|
|
haentschman
      
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Sa 02.07.11 09:16
Ähmm... das war nicht böse gemeint.  Tschuldigung, Sorry... ich hab nicht ins Profil geguckt.
Für mich las sich das beim Überfliegen wie ein automatisch übersetzter Text.
| Zitat: | | Ich habe mit Delphi 2007 und Delphi XE probiert. |
Vieleicht war es auch nur zu früh für mich...
|
|
Teekeks
      
Beiträge: 211
Erhaltene Danke: 23
|
Verfasst: Sa 02.07.11 12:50
|
|
SvenAbeln
      
Beiträge: 334
Erhaltene Danke: 3
|
Verfasst: Sa 02.07.11 15:08
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Sa 02.07.11 22:48
|
|
jaenicke
      
Beiträge: 19338
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 03.07.11 13:47
Boldar hat folgendes geschrieben : | | Evtl. wird da schon der Standard-Konstruktor aufgerufen, und du rufst dann Create nochmals auf, wobei das alte Objekt im Nirwana landet? Du kannst ja vielleicht einfach den alten Konstruktor benutzen und dann FTimeToWork von aussen setzen (dann als property umbauen). |
Nein, das ist genau der richtige Weg so...
Es wird zuerst das Feld gesetzt, damit der Wert in Execute schon zur Verfügung steht und dann wird der geerbte Konstruktor aufgerufen, der den Thread startet.
Auf die Weise kann der Thread auch sofort loslaufen und muss nicht pausiert erstellt werden. (Was er hier aber dennoch wird, deshalb geht es hier auch als Property.)
Wenn du den Wert erst hinterher setzt, musst du ja sicherstellen, dass Execute nicht vorher schon ausgeführt wird... (z.B. wie hier durch pausiertes Starten)
|
|
Geri 
      
Beiträge: 78
XP
RAD Studio XE pro
|
Verfasst: Mo 04.07.11 20:42
Hallo zusammen
Vielen Dank für eure ausführliche Hilfe! Mit FreeOnTerminate hatte ich getestet. Wahrscheinlich hatte ich aber ein Brett vor dem Kopf...
Beste Grüsse und Danke nochmals!
Geri
PS: "die Thread" war nicht Absicht sondern ein Tippfehler.
|
|