/ Forside / Teknologi / Udvikling / Delphi/Pascal / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Delphi/Pascal
#NavnPoint
oldwiking 603
jrossing 525
rpje 520
EXTERMINA.. 500
gandalf 460
gubi 270
DJ_Puden 250
PARKENSS 230
technet 210
10  jdjespers.. 200
Thread / afslutning
Fra : Harald


Dato : 07-01-03 13:24

Hej

Jeg har et program hvori jeg benytter en enkelt TThread, programmet kan ikke
lukkes før tråden er afsluttet. Jeg kalder Terminate men da jeg bruger en
indy komponent i tråden som jo er blocked kan der gå lidt tid inden tråden
afsluttes. Hvordan håndtere man bedst dette?

Jeg bruger Delphi 7

Mvh
HK



 
 
Lars B. Dybdahl (07-01-2003)
Kommentar
Fra : Lars B. Dybdahl


Dato : 07-01-03 13:53

Sætter timeout på indy komponenten. Alternativt kan du prøve at dræbe tråden
med Windows API kald.

Jeg har i et enkelt tilfælde været nødt til at gå ind i source koden på Indy
for at lave noget med timeout. Jeg kan ikke huske årsagen, men det var
vistnok også noget med TThreads, og nemlig også noget med nedlukning. Så
hvis du ikke nemt kan sætte en timeout, så overvej at ændre i Indy source
koden.

Hilsen,

Lars.

Harald wrote:
> Jeg har et program hvori jeg benytter en enkelt TThread, programmet kan
> ikke lukkes før tråden er afsluttet. Jeg kalder Terminate men da jeg
> bruger en indy komponent i tråden som jo er blocked kan der gå lidt tid
> inden tråden afsluttes. Hvordan håndtere man bedst dette?

--

Dybdahl Engineering: http://dybdahl.dk/
Delphi brugergruppen DAPUG: http://dapug.dk/


Harald (07-01-2003)
Kommentar
Fra : Harald


Dato : 07-01-03 14:57

"Lars B. Dybdahl" <Lars@dybdahl.dk> skrev i en meddelelse
news:3e1acd8d$0$259$edfadb0f@dread12.news.tele.dk...
> Sætter timeout på indy komponenten. Alternativt kan du prøve at dræbe
tråden
> med Windows API kald.
>
> Jeg har i et enkelt tilfælde været nødt til at gå ind i source koden på
Indy
> for at lave noget med timeout. Jeg kan ikke huske årsagen, men det var
> vistnok også noget med TThreads, og nemlig også noget med nedlukning. Så
> hvis du ikke nemt kan sætte en timeout, så overvej at ændre i Indy source
> koden.

Jeg har sat en timeout på indy så det er ikke noget problem, det jeg gerne
vil vide er hvordan man bedst løser tingene i hovede formen. Det skal vel
være noget med at man i OnClosequery kalder Terminate og så venter på at
thread´en afslutter, men hvordan ved man hvornår thread´en er afsluttet, ja
man bruger ved OnTerminate eller hur?

Mvh
HK



Stig Johansen (07-01-2003)
Kommentar
Fra : Stig Johansen


Dato : 07-01-03 21:14

Hej.

"Harald" <swobu@kroning.dk> wrote in message
news:3e1adcbd$0$71685$edfadb0f@dread11.news.tele.dk...
[snip]
> Jeg har sat en timeout på indy så det er ikke noget problem, det jeg gerne
> vil vide er hvordan man bedst løser tingene i hovede formen. Det skal vel
> være noget med at man i OnClosequery kalder Terminate og så venter på at
> thread´en afslutter, men hvordan ved man hvornår thread´en er afsluttet,
ja
> man bruger ved OnTerminate eller hur?

Netop. Lav en variabel, 'threadactive', der sættes til true ved creering af
tråden.
Lav derefter en procedure, der kaldes ved threadterminet. Proceduren sætter
'threadactive' til false.

I din QnCloseQuery, laver du et loop
while threadactive do
sleep(100); // eller hvad du nu synes

Bemærk, at denne her kun gælder for en enkelt tråd. Hvis du har flere aktive
skal du ud i noget mere kompliceret kode.

--

Med venlig hilsen/Best regards
Stig Johansen
Stig.Johansen@udvikling.it.dk
(remove dot dk)




Harald (07-01-2003)
Kommentar
Fra : Harald


Dato : 07-01-03 21:30

"Stig Johansen" <stig.johansen@udvikling.it> skrev i en meddelelse
news:avfc7v$n73$1@sunsite.dk...
> Hej.
>
> "Harald" <swobu@kroning.dk> wrote in message
> news:3e1adcbd$0$71685$edfadb0f@dread11.news.tele.dk...
> [snip]
> > Jeg har sat en timeout på indy så det er ikke noget problem, det jeg
gerne
> > vil vide er hvordan man bedst løser tingene i hovede formen. Det skal
vel
> > være noget med at man i OnClosequery kalder Terminate og så venter på at
> > thread´en afslutter, men hvordan ved man hvornår thread´en er afsluttet,
> ja
> > man bruger ved OnTerminate eller hur?
>
> Netop. Lav en variabel, 'threadactive', der sættes til true ved creering
af
> tråden.
> Lav derefter en procedure, der kaldes ved threadterminet. Proceduren
sætter
> 'threadactive' til false.
>
> I din QnCloseQuery, laver du et loop
> while threadactive do
> sleep(100); // eller hvad du nu synes
>
> Bemærk, at denne her kun gælder for en enkelt tråd. Hvis du har flere
aktive
> skal du ud i noget mere kompliceret kode.

Men er det overhoved nødvendig at afslutte trådene, har fundet ud af at hvis
jeg kalder trådens Suspend finktion så kan jeg afslutte programmet uden
fejl, hvis jeg ikke kalder Suspend og indy komponenter i tråden er aktiv så
får jeg en fejl.

Mvh
HK



Stig Johansen (08-01-2003)
Kommentar
Fra : Stig Johansen


Dato : 08-01-03 08:06

Hej.

"Harald" <swobu@kroning.dk> wrote in message
news:3e1b38e1$0$71686$edfadb0f@dread11.news.tele.dk...
[snip]

> Men er det overhoved nødvendig at afslutte trådene, har fundet ud af at
hvis
> jeg kalder trådens Suspend finktion så kan jeg afslutte programmet uden
> fejl, hvis jeg ikke kalder Suspend og indy komponenter i tråden er aktiv

> får jeg en fejl.

Det kommer jo lidt an på din programmerings stil.
Personligt sørger jeg altid for, at en tråd suspendes(v/pooling) eller
afsluttes korrekt. Hvis man ikke for ryddet op i tråden(e), typisk i
destroy, står man med memory leaks.
Og vær opmærksom på, at Indy ikke er fejlfri.

--

Med venlig hilsen/Best regards
Stig Johansen
Stig.Johansen@udvikling.it.dk
(remove dot dk)






Henry (11-01-2003)
Kommentar
Fra : Henry


Dato : 11-01-03 21:57

> Jeg har et program hvori jeg benytter en enkelt TThread, programmet kan
ikke
> lukkes før tråden er afsluttet. Jeg kalder Terminate men da jeg bruger en
> indy komponent i tråden som jo er blocked kan der gå lidt tid inden tråden
> afsluttes. Hvordan håndtere man bedst dette?
>
> Jeg bruger Delphi 7
>

Jeg bruger Delphi6 og jeg laver threads efter følgende regler.

1. Den tråd/programdel der opretter en anden tråd, sørger også for at a
terminerer den.
2. Jeg bruger aldrig FreeOnTerminate.
3. Jeg bruger Events, Mutex til at signalere og synkroniserer threads.
4. Jeg bruger postmessage og sendmessage til at kommunikere mellem thread og
parent


Jeg siger ikke min metode er den eneste rigtige men den virker stabilt.
Bemærk at jeg benytter TThread.Terminate til at sparke en ventende Thread
igen midt i en Wait, du vil kunne gøre det samme med suspend.

Eksempelvis:

procedure TMainForm.CreateThreads;
begin
try
hMutex := CreateMutex(nil, false, nil);
hDDEWatchdogMutex := CreateMutex(nil, false, nil);
hAlarmScanEvent := CreateEvent(nil, false, false, 'AlarmScanEvent');
hDDEWatchdogEvent := CreateEvent(nil, false, false, 'DDEWatchdogEvent');
hPrintScanEvent := CreateEvent(nil, false, false, 'PrintScanEvent');
hScheduleEvent := CreateEvent(nil, false, false, 'ScheduleEvent');

AlarmScanThr := TAlarmScanThr.create(handle);
ThreadHandelArray[0] := AlarmScanThr.handle;

ScheduleThr := TScheduleThr.create(handle);
ThreadHandelArray[1] := ScheduleThr.handle;

WatchdogThr := TWatchdogThr.create(handle);
ThreadHandelArray[2] := WatchdogThr.handle;

PrintScanThr := TPrintScannerThr.create(handle);
ThreadHandelArray[3] := PrintScanThr.handle;
except
on e:exception do LogError(lcErrorEvents ,format('Mainform.CreateThreads
%s', [e.message]));
end;
end;


procedure TMainForm.TerminateThreads;
begin
try
AlarmScanThr.Terminate;
ScheduleThr.Terminate;
PrintScanThr.Terminate;
WatchdogThr.Terminate;

case WaitForMultipleObjects(4, @ThreadHandelArray[0], true, 20000) of
WAIT_TIMEOUT : begin
LogError(lcErrorEvents,'MainForm.TerminateThreads WAIT_TIMEOUT');
end;
end;

if AlarmScanThr <> nil then AlarmScanThr.Free;
if ScheduleThr <> nil then ScheduleThr.Free;
if WatchdogThr <> nil then WatchdogThr.Free;
if PrintScanThr <> nil then PrintScanThr.Free;

closeHandle(hMutex);
closeHandle(hDDEWatchdogMutex);
closeHandle(hAlarmScanEvent);
closeHandle(hDDEWatchdogEvent);
closeHandle(hPrintScanEvent);
closeHandle(hScheduleEvent);
except
on e:exception do LogError(lcErrorEvents, format('TerminateThreads %s',
[e.message]));
end;
end;

// thread

unit thScheduler;
interface

uses
Classes, sysutils, controls, dialogs, windows, uAlarmData,
uLocalVariables,
uLocalFunctions, uGlobalVariables, uPrinterstuff, messages, extctrls;

type
TScheduleThr = class(TThread)
private
{ Private declarations }
hCaller : Thandle;
hTimer : THandle;
hTerminateScheduleThread : Thandle;
lpDueTime: Int64; // dummy variable
function ActiveException : boolean;
function ActiveDayPeriode : boolean;
protected
procedure Execute; override;
Procedure Schedule;
public
constructor create(AhCaller : THandle);
destructor Destroy; override;
procedure StartPeriodicTimer(IntervalInSecs : Int64);
procedure StopPeriodicTimer;
procedure Terminate;
end;

implementation

uses fmMain, dmDoaVista;

constructor TScheduleThr.create(AhCaller : THandle);
begin
try
inherited create(true); // create suspended
hCaller := AhCaller;
FreeOnTerminate := false;
hTimer := CreateWaitableTimer(nil, false, 'ScheduleTimer');
hTerminateScheduleThread := CreateEvent(nil, false, false,
'TerminateScheduleThread');
resume;
except
on e:exception do LogError(lcErrorEvents,format('Fejl under create
scheduler %s',[e.message]));
end;
end;


procedure TScheduleThr.Terminate;
begin
// cancel the INFINITE waiting
SetEvent(hTerminateScheduleThread);
inherited Terminate;
end;

procedure TScheduleThr.StartPeriodicTimer(IntervalInSecs : Int64);
begin
LogError(lcThreadEvents,format('TScheduleThr.StartPeriodicTimer %d
secs',[IntervalInSecs]));
if IntervalInSecs = 0 then IntervalInSecs := 60;
lpDueTime := -IntervalInSecs * 10000000; // Run at once
SetWaitableTimer(hTimer, // handle to a timer object
lpDueTime, // when timer will become signaled
IntervalInSecs*1000, // periodic timer interval
nil, // pointer to the completion routine
nil, // data passed to the completion routine
false // flag for resume state
);
end;

procedure TScheduleThr.StopPeriodicTimer;
begin
LogError(lcThreadEvents, 'TScheduleThr.StopPeriodicTimer');
CancelWaitableTimer(hTimer);
end;

destructor TScheduleThr.Destroy;
begin
try
LogError(lcThreadEvents, 'TScheduleThr.Destroy');
CancelWaitableTimer(hTimer);
CloseHandle(hTimer);
closeHandle(hTerminateScheduleThread);
except
on e:exception do LogError(lcErrorEvents,'TScheduleThr.destroy ' +
e.message);
end;
end;


Procedure TScheduleThr.Schedule;
var
hArray : array[0..1] of thandle;
begin
try
hArray[0] := hMutex;
hArray[1] := hTerminateScheduleThread;
case WaitForMultipleObjects(2,@hArray[0], false, INFINITE) of
WAIT_OBJECT_0 :
try
if terminated then exit;
postmessage(hCaller, WM_SCHEDULER_STARTED, 0, 0);
// work work work
finally
postmessage(hCaller, WM_SCHEDULER_DONE, 0, 0);
ReleaseMutex(hMutex);
end; // try

end; // case WaitForSingleObject(hMutex, ) of
end;

procedure TScheduleThr.Execute;
var
hArray : Array[0..2] of THandle;
begin
try
hArray[0] := hTimer;
hArray[1] := hScheduleEvent;
hArray[2] := hTerminateScheduleThread;
while not terminated do
begin
case WaitForMultipleObjects(3, @hArray[0], false, INFINITE) of //
trigger objects
WAIT_OBJECT_0 : begin
LogError(lcThreadEvents,'TScheduleThr.Execute hTimer
received');
if terminated then break;
Schedule;
end;
WAIT_OBJECT_0 + 1 : begin
LogError(lcThreadEvents,'TScheduleThr.Execute hScheduleEvent
received');
if terminated then break;
Schedule;
end; // WAIT_OBJECT_0 timer

WAIT_OBJECT_0 + 2 : begin
LogError(lcThreadEvents,'TScheduleThr.Execute
hTerminateScheduleThread received');
break;
end;
end; // case wait timer
end; // while not terminated
except
on e:exception do LogError(lcErrorEvents, format('TScheduleThr.Execute
%s',[e.message]));
end;
end;

end.






Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408924
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste