Hallo,
Umgebung:
Rad Studio XE3 Update 2
Ich habe einen Thread (MThread), der während beim Click auf einen Button erzeugt wird. Mit Option freeonterminate=true
Ein Ereignis onThreadTerminate wird zugewiesen.
Nach Auslösen dieses Ereignisses wird einiges abgearbeitet - klappt auch alles soweit.
Nur ein merkwürdiges Phänomen tritt auf: Wenn ich irgendwann später MThread.terminated abfrage, so ist dieser immer noch aktiv. - Es stört nicht wirklich. Auch ein erneutes Erzeugen und Starten klappt problemlos.
Mache ich allerdings beim FormClose die Zeile: if assigned(MThread) then freeandnil(MThread) rein, knallt es.
(Stört Euch nicht an der Formvariable oder so - ich arbeite hier mit einem multiple Docked-Forms Konzept,
wo alle FRMs im Prinzip nur Muster sind und die Childforms dynamisch erzeugt werden - somit kann jede FRM
mit eindeutigem Namen versehen werden und ich nutze da auch verschiedene Muster)
Meine Problematik dreht sich nur um diesen MThread
Hier mal ein wenig Code:
Delphi-Quellcode:
type
TFrmGMaps = class(TChildform)
WebGMaps1: TWebGMaps;
starttimer: TTimer;
.
.
. weitere Definitionen ...
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
TMyThread = class(TThread)
procedure execute; override;
end;
var
threadaktiv : Boolean = False;
MThread : TMyThread;
// Form2 - Formvariable verworfen, wird bei Aufruf vergeben (Mutliple Forms)
implementation
{$R *.dfm}
uses main, childformverwaltung, System.StrUtils, UDM;
procedure TFrmGMaps.threadabschluss;
var idx : integer;
lat : string;
lng : string;
buwID : string;
KName : string;
begin
if not threadaktiv then begin
threadtimer.Enabled := false;
pan_warten.Visible := false;
setstartmarker;
for idx := 0 to Length(threadkname)-1 do begin
lat := threadlat[idx];
lng := threadlng[idx];
KName := threadKName[idx];
if ((lat<>'') and (lng<>'')) then WebGMaps1.Markers.Add(strtofloat(lat),strtofloat(lng),
ID+' '+KName,geticon(99, False),
True,True,True,False,false,idx);
end;
SetLength(threadlat,0);
SetLength(threadlng,0);
SetLength(threadkname,0);
pan_gmapsteuerung.Visible := True;
end;
end;
procedure TMyThread.Execute;
var idx : integer;
dynform : TFrmGMaps;
// GETCUMLIST_DIST_FROM ist ne ORacle Stored Proc
begin
SetLength(threadlat,0);
SetLength(threadlng,0);
SetLength(threadkname,0);
dynform := TFrmGMaps(Application.FindComponent(FrmMain.GmapThreadname));
dynform.GETCUMLIST_DIST_FROM.execute;
if dynform.GETCUMLIST_DIST_FROM.ParamByName('RESULT').Asinteger=DM.pkgCodes.VariableByName('INF_SUCCESS').AsInteger then
begin
idx := 0;
dynform.JvGradientProgressBar1.Max := dynform.GETCUMLIST_DIST_FROM.RecordCount;
SetLength(threadlat,dynform.GETCUMLIST_DIST_FROM.RecordCount);
SetLength(threadlng,dynform.GETCUMLIST_DIST_FROM.RecordCount);
SetLength(threadkname,dynform.GETCUMLIST_DIST_FROM.RecordCount);
while (not dynform.GETCUMLIST_DIST_FROM.eof) do begin
Synchronize(dynform.JvGradientProgressBar1.StepIt);
inc(idx);
if not ((dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLAT.AsString = dynform.gmaps_lat) // Um auszuschließen, das der Startmarker
and ( dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLNG.AsString = dynform.gmaps_lng)) // überschrieben wird
then begin
SetLength(threadlat,idx);
SetLength(threadlng,idx);
SetLength(threadkname,idx);
threadlat[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLAT.AsString;
threadlng[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLNG.AsString;
threadkname[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_STRNAME.AsString;
end;
dynform.GETCUMLIST_DIST_FROM.Next;
end;
dynform.GETCUMLIST_DIST_FROM.Close;
end
else
begin
//Fehler
end;
end;
procedure TFrmGMaps.btn_querystartClick(Sender: TObject);
var lat : string;
lng : string;
KName : string;
idx : integer;
begin
WebGMaps1.DeleteAllMapMarker;
FrmMain.GmapThreadname := Self.Name;
JvGradientProgressBar1.Position := 1;
pan_warten.Left := Integer(Trunc((Self.Width - pan_warten.Width) / 2));
pan_warten.Top := Integer(Trunc((Self.Height - pan_warten.Height) / 2));
pan_warten.Visible := True;
Application.ProcessMessages;
MThread := TMyThread.Create(True);
MThread.FreeOnTerminate := True;
threadaktiv := true;
MThread.OnTerminate := threadend;
pan_gmapsteuerung.Visible := false;
MThread.Resume;
end;
procedure TFrmGMaps.threadend(Sender: TObject);
begin
threadaktiv := false;
threadabschluss;
end;
irgendwo - irgendwann muss der Thread ja "zerstört" werden?
Gruss
MC