Hallo Ihr,
ich glaube, ich bräuchte bitte mal etwas CodeReview von Euch.
Ausgangslage:
In einer DB soll je Datensatz ein und derselbe Thread erneut gestartet werden (Zweck: Download, Images).
Stand der Dinge:
Im dem im Thread erstellenden Event kann ich natürlich feststellen, ob ein solcher Thread bereits existiert (der vom letzten Datensatz) und den dann terminieren und nach WaitFor auch freigeben (FreeOnTerminate ist nicht gesetzt).
ABER ...
Problem:
Wann genau free'e ich den letzten Thread? Den, der u.U. normal zum Abschluss gekommen ist, weil kein weiterer RecordChange anstand oder, wie in meinem Testfall hier, kein weiterer Click in der Listbox erfolgt ist?
Erst im OnClose des Forms ist mir irgendwie zu ungenau. Oder sollte ein := nil im OnTerminate-Eveent AfterThreadFinished reichen? Eigentlich nicht, da FreeOnTerminate := False ist.
Kurz gesagt, es geht mir um den abschließenden Free/FreeAndNil(), der hier irgendwie noch fehlt.
Danke für Eure Aufmerksamkeit!
Gruss
nru
Hier mal mein Testproggi (mit einer Listbox und ihrem OnClick anstelle der DB):
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:
| type TForm1 = class(TForm) ListBox1: TListBox; Label1: TLabel; Button1: TButton; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure ListBox1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private procedure OnThreadWork( Sender: TThread; count: Integer ); procedure OnThreadWorkBegin( Sender: TThread; count: Integer ); procedure AfterThreadFinished( Sender: TObject ); public end;
var Form1: TForm1;
implementation
uses SelfThread;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject); var i: Integer; begin for i := 0 to 1000 do Listbox1.Items.Add( IntToStr( i ) ); end;
procedure TForm1.ListBox1Click(Sender: TObject); begin
if Assigned( FSelfThread ) then begin with FSelfThread do begin Terminate; WaitFor; end; FreeAndNil( FSelfThread ); end;
if FSelfThread = nil then begin FSelfThread := TGoogleWSThread.Create(AfterThreadFinished); FSelfThread.OnWork := OnThreadWork; FSelfThread.Resume; end;
end;
procedure TForm1.AfterThreadFinished( Sender: TObject ); begin label2.Caption := IntToStr( FSelfThread.FTime ); end; procedure TForm1.OnThreadWork( Sender: TThread; count: Integer ); begin label1.Caption := IntToStr( count ); end; procedure TForm1.OnThreadWorkBegin( Sender: TThread; count: Integer ); begin label2.Caption := IntToStr( count ); end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin if Assigned( FSelfThread ) then begin with FSelfThread do begin Terminate; WaitFor; end; FreeAndNil( FSelfThread ); end; end;
end. |
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:
| TOnWorkEvent = procedure( sender: TThread; count: Integer ) of object;
TGoogleWSThread = class(TThread) private FCounter: Integer; FOnWork: TOnWorkEvent; FOnWorkBegin: TOnWorkEvent; procedure DoNotifyWork; procedure DoNotifyWorkBegin(); protected procedure Execute; override; public FTime: Integer; constructor Create(Callback: TNotifyEvent); property OnWork: TOnWorkEvent read FOnWork write FOnWork; property OnWorkBegin: TOnWorkEvent read FOnWorkBegin write FOnWorkBegin; end;
var FSelfThread: TGoogleWSThread;
implementation
constructor TGoogleWSThread.Create(Callback: TNotifyEvent); begin inherited Create( true ); OnTerminate := callback; end;
procedure TGoogleWSThread.Execute; var i: Integer; begin FCounter := 0; FTime := GetTickCount(); Synchronize( DoNotifyWorkBegin ); for i := 0 to 5000 do begin Inc( FCounter ); Sleep(1); Synchronize( DoNotifyWork ); if Terminated then break; end; FTime := (GetTickCount - FTime); end;
procedure TGoogleWSThread.DoNotifyWork(); begin if Assigned( OnWork ) then OnWork( self, FCounter ); end; procedure TGoogleWSThread.DoNotifyWorkBegin(); begin if Assigned( OnWorkBegin ) then OnWorkBegin( self, FCounter ); end; |