/ 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
Fejl besked
Fra : Harald


Dato : 14-03-04 15:15

Hej

Jeg får en gang i mellem denne fejl når mit program afsluttes:
Error retrieving statistics(6), Handlen er ikke gyldig.

Hvad betyder det? Jeg bruger delphi 7 og Windows XP

Mvh
HK



 
 
Henry (14-03-2004)
Kommentar
Fra : Henry


Dato : 14-03-04 22:11

> Hej
>
> Jeg får en gang i mellem denne fejl når mit program afsluttes:
> Error retrieving statistics(6), Handlen er ikke gyldig.
>
> Hvad betyder det? Jeg bruger delphi 7 og Windows XP
>

Tja, det betyder at en eller anden programstump referere til en pointer
eller et object som er blevet nedlagt, som derved gør den handle ugyldig.

Årsagen er stort set umulig at gætte uden at vide mere end det du skriver.

mvh
Henry



Harald (14-03-2004)
Kommentar
Fra : Harald


Dato : 14-03-04 23:26

"Henry" <henry@nomail.com> skrev i en meddelelse
news:4054ca46$0$1633$edfadb0f@dread14.news.tele.dk...
> > Hej
> >
> > Jeg får en gang i mellem denne fejl når mit program afsluttes:
> > Error retrieving statistics(6), Handlen er ikke gyldig.
> >
> > Hvad betyder det? Jeg bruger delphi 7 og Windows XP
> >
>
> Tja, det betyder at en eller anden programstump referere til en pointer
> eller et object som er blevet nedlagt, som derved gør den handle ugyldig.
>
> Årsagen er stort set umulig at gætte uden at vide mere end det du skriver.

Fejlen kommer kun en gang i mellem når programmet lukkes. Når programmet
lukkes afslutter jeg 3 tråde og free´er nogle TStringList og nogle TInifile.

/HK



Henry (15-03-2004)
Kommentar
Fra : Henry


Dato : 15-03-04 22:29

> > >
> > > Jeg får en gang i mellem denne fejl når mit program afsluttes:
> > > Error retrieving statistics(6), Handlen er ikke gyldig.
> > >
> > > Hvad betyder det? Jeg bruger delphi 7 og Windows XP
> > >
> >
> > Tja, det betyder at en eller anden programstump referere til en pointer
> > eller et object som er blevet nedlagt, som derved gør den handle
ugyldig.
> >
> > Årsagen er stort set umulig at gætte uden at vide mere end det du
skriver.
>
> Fejlen kommer kun en gang i mellem når programmet lukkes. Når programmet
> lukkes afslutter jeg 3 tråde og free´er nogle TStringList og nogle
TInifile.

Hvor befinder de TStringList sig? Hvem er "owner"? mainformen, threads
eller?

Hvordan styre du dine threads, create, terminate destroy osv?

Ud af busken og vis os hvad du gør.

mvh
Henry



Harald (15-03-2004)
Kommentar
Fra : Harald


Dato : 15-03-04 23:19

"Henry" <henry@nomail.com> skrev i en meddelelse
news:4056200c$0$484$edfadb0f@dread14.news.tele.dk...
> > > >
> > > > Jeg får en gang i mellem denne fejl når mit program afsluttes:
> > > > Error retrieving statistics(6), Handlen er ikke gyldig.
> > > >
> > > > Hvad betyder det? Jeg bruger delphi 7 og Windows XP
> > > >
> > >
> > > Tja, det betyder at en eller anden programstump referere til en
pointer
> > > eller et object som er blevet nedlagt, som derved gør den handle
> ugyldig.
> > >
> > > Årsagen er stort set umulig at gætte uden at vide mere end det du
> skriver.
> >
> > Fejlen kommer kun en gang i mellem når programmet lukkes. Når programmet
> > lukkes afslutter jeg 3 tråde og free´er nogle TStringList og nogle
> TInifile.
>
> Hvor befinder de TStringList sig? Hvem er "owner"? mainformen, threads
> eller?
>
> Hvordan styre du dine threads, create, terminate destroy osv?
>
> Ud af busken og vis os hvad du gør.

Ok

I min mainform´s class har jeg defineret følgende:

TCPThread : TTCPThread;
SQLThread : TSQLThread;
SerThread : TSerThread;
// disse 3 har alle TThread som ancestor class

SystemIni : TInifile;
KunderIni,
PunkterIni,
RettighederIni : TMemInifile;

TCP_FIFOList : TStringList;
FraSerFIFOList : TStringList;
TilSerFIFOList : TStringList;
LogDataTilSQL : TStringList;

I mainformens OnCreate opretter jeg alle TInifile, TMemInifile og
TStringList.
I mainformens OnActivate bliver de 3 tråde oprettet hvor jeg også sætter en
OnTerminate på dem alle

I mainformens OnCloseQuery kaldes følgende:
TCPThread.Terminate;
TCPThread.WaitFor;
TCPThread.Free;

SQLThread.Terminate;
SQLThread.WaitFor;
SQLThread.Free;

SerThread.Terminate;
SerThread.WaitFor;
SerThread.Free;
// ************ fejlen kommer her ***************

CloseAllInifiles; // denne funktion kalder free på alle TInifile

TCP_FIFOList.Free;
FraSerFIFOList.Free;
TilSerFIFOList.Free;
LogDataTilSQL.Free;

SerThread trådens OnTerminate bliver kaldt så tråden bliver altså afsluttet,
men jeg er nået frem til at fejlen kommer lige efter at denne tråd er
afsluttet.

De 3 tråde opretter henholdsvis en TCP forbindelse til en anden computer, en
SQL forbindelse til en MySQL server og den sidste en forbindelse til en
lokal RS232 port. Ingen af de 3 tråde afsluttes før de har lukket for deres
forbindelser.

Mvh
HK



Henry (16-03-2004)
Kommentar
Fra : Henry


Dato : 16-03-04 19:53

> >
> > Ud af busken og vis os hvad du gør.
>
> Ok
>

Ok, hvis problemet er identisk for alle tre tråde så vis mig en af dine
tråde. (den hele)

mvh
Henry



Harald (16-03-2004)
Kommentar
Fra : Harald


Dato : 16-03-04 20:36

"Henry" <henry@nomail.com> skrev i en meddelelse
news:40574cf5$0$455$edfadb0f@dread14.news.tele.dk...
> > >
> > > Ud af busken og vis os hvad du gør.
> >
> > Ok
> >
>
> Ok, hvis problemet er identisk for alle tre tråde så vis mig en af dine
> tråde. (den hele)

Så får du TCP tråden, det er den mindste:

unit TCPThreadUnit;

interface

uses
Classes, Messages, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient;

const
WM_ThreadMessage = WM_User+1;

type
TTCPThread = class(TThread)
private
{ Private declarations }
IdTCPClient: TIdTCPClient;
LogTekst : string;
LastOpenTry : Cardinal;
ModtagetDel : string;
TekstInFIFOList : boolean;
SendDataList : TStringList;

procedure MainLog;
procedure MessageLoop;
procedure ReadData;
procedure OpenClientSocket;
procedure SkrivTilMainLog(Tekst : string);
procedure SendTekst(Tekst : string);
procedure ProcessData;
procedure HentFraFIFOList;
procedure SendData;
protected
procedure Execute; override;

public
constructor Create(Host : String;Port : integer);
destructor Destroy; override;
end;

implementation

uses KDSatMainUnit, Windows;

{ TCPThread }

constructor TTCPThread.Create(Host : string;Port : integer);
begin
inherited Create(False);

FreeOnTerminate:=false;

IdTCPClient:=TIdTCPClient.Create(nil);
IdTCPClient.Port:=Port;
IdTCPClient.Host:=Host;

TekstInFIFOList:=true;
SendDataList:=TStringList.Create;
end;

destructor TTCPThread.Destroy;
begin
IdTCPClient.Free;
inherited;
end;

procedure TTCPThread.MainLog;
begin
KDSatMainForm.SkrivLog(LogTekst);
end;

procedure TTCPThread.SkrivTilMainLog(Tekst : string);
begin
LogTekst:=Tekst;
Synchronize(MainLog);
end;

procedure TTCPThread.OpenClientSocket;
begin
try
SkrivTilMainLog('Forsøger TCP open');
IdTCPClient.Connect;
SkrivTilMainLog('TCP open - OK');

SendTekst('Kodeord: xxxxxxxxxx');
SkrivTilMainLog('Kodeord sendt');
except
SkrivTilMainLog('Fejl i TCP open');
end;
end;

procedure TTCPThread.SendTekst(Tekst : string);
begin
if not IdTCPClient.Connected then
exit;

try
IdTCPClient.Write(Tekst+#13);
except
SkrivTilMainLog('Fejl i Write');
LastOpenTry:=GetTickCount;
end;
end;

procedure TTCPThread.MessageLoop;
var
Msg : TMsg;
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if Msg.message=WM_ThreadMessage then
begin
// SkrivTilMainLog('TCP Message modtaget');

if Msg.wParam=1 then // der er ting i FIFO listen
TekstInFIFOList:=true;

if Msg.wParam=2 then
SendTekst('hello hello'); // til test
end;
end;
end;

procedure TTCPThread.ProcessData;
begin
KDSatMainForm.ProcessTCPData(ModtagetDel);
end;

procedure TTCPThread.ReadData;
var
Tekst : string;
begin
try
Tekst:=IdTCPClient.ReadLn(#13,50);
except
SkrivTilMainLog('Fejl i readln');
try
IdTCPClient.Disconnect;
except
SkrivTilMainLog('Fejl i Disconnect');
end;
end;

if Tekst<>'' then
begin
ModtagetDel:=Tekst;
Synchronize(ProcessData);
end;
end;

procedure TTCPThread.HentFraFIFOList;
begin
SendDataList.AddStrings(KDSatMainForm.TCP_FIFOList);
KDSatMainForm.TCP_FIFOList.Clear;
TekstInFIFOList:=false;
end;

procedure TTCPThread.SendData;
begin
if SendDataList.Count=0 then
exit;

SendTekst(SendDataList.Strings[0]);
SendDataList.Delete(0);
end;

procedure TTCPThread.Execute;
begin
LastOpenTry:=GetTickCount;

repeat
if not IdTCPClient.Connected then
begin
if GetTickCount>LastOpenTry+Cardinal(Random(5000)+10000) then // forsøger
hver 10-15 sek.
begin
LastOpenTry:=GetTickCount;
OpenClientSocket;
end;
end
else
ReadData;

if TekstInFIFOList then
Synchronize(HentFraFIFOList);
SendData; // der hentes og sendes selvom der ikke er forbindelse hvis det
ikke gøres sådan så vil der
// i løbet af natten blive opbygget en lang liste som så vil komme
væltende så der logges på

MessageLoop;
Sleep(1); // for at undgå at der bruges 100% cpu når ReadLn (50 ms wait)
ikke kaldes
until Terminated;

if IdTCPClient.Connected then
IdTCPClient.Disconnect;

repeat
until not IdTCPClient.Connected;
end;

end.

/HK



Henry (16-03-2004)
Kommentar
Fra : Henry


Dato : 16-03-04 21:08

> Så får du TCP tråden, det er den mindste:
Måske skulle vi hellere se SerThread hvis det er den der laver ballade?

Jeg har allerede nogle småting til dig, men lad mig lige se den SerThread
kode.

mvh
Henry



Harald (16-03-2004)
Kommentar
Fra : Harald


Dato : 16-03-04 21:38

"Henry" <henry@nomail.com> skrev i en meddelelse
news:40575e8f$0$449$edfadb0f@dread14.news.tele.dk...
> > Så får du TCP tråden, det er den mindste:
> Måske skulle vi hellere se SerThread hvis det er den der laver ballade?
>
> Jeg har allerede nogle småting til dig, men lad mig lige se den SerThread
> kode.

Hvilke småting?

/HK



Henry (16-03-2004)
Kommentar
Fra : Henry


Dato : 16-03-04 22:14

Hej Harald

Okay, nu hvor vi har lidt kode.

Her er lidt forslag, men jeg har slet ikke skrevet færdigt, du er jo
utålmodig.

* Du skulle tage at kikke på waitformultipleobjects, mutex og events, det
vil give dig en langt lettere måde at styre dine tråde på, samtidigt ville
du slippe for at "poll" efter data i et loop.
* Hvorfor har du et messageloop, hvis du benytter ovenstående behøver du
ikke det lopp og du behøver heller ikke sleep for at undgå 100% CPU load.
* Du har et ekstra loop til sidst i din execute, der er ingen sleep, prøv at
fjerne det loop i første omgang.
* Jeg tror du risikere en deadlock situation når du bruger waitfor og
samtidigt risikere at gå ind i dit lopp hvor du forsøger at få adgang til
objecter på din mainform vis synchronize.
* Læg dine free diverse under din mainforms OnDestroy.

Jeg har også et par småting som intet har med dit problem at gøre

I din tcp tråd glemmer du vist
SendDataList.free? i destroy

mvh
Henry



Stig Johansen (17-03-2004)
Kommentar
Fra : Stig Johansen


Dato : 17-03-04 07:11

Henry wrote:

> Hej Harald
>
> Okay, nu hvor vi har lidt kode.
>
> Her er lidt forslag, men jeg har slet ikke skrevet færdigt, du er jo
> utålmodig.

Og når vi snakker multithreaded programmering, vil jeg anbefale at bruge
synapse i stedet for indy til din TCP kommunikation.

--
Med venlig hilsen
Stig Johansen

Harald (18-03-2004)
Kommentar
Fra : Harald


Dato : 18-03-04 17:41

Henry" <henry@nomail.com> skrev i en meddelelse
news:40576deb$0$485$edfadb0f@dread14.news.tele.dk...
> Hej Harald
>
> Okay, nu hvor vi har lidt kode.
>
> Her er lidt forslag, men jeg har slet ikke skrevet færdigt, du er jo
> utålmodig.
>
> * Du skulle tage at kikke på waitformultipleobjects, mutex og events, det
> vil give dig en langt lettere måde at styre dine tråde på, samtidigt ville
> du slippe for at "poll" efter data i et loop.
> * Hvorfor har du et messageloop, hvis du benytter ovenstående behøver du
> ikke det lopp og du behøver heller ikke sleep for at undgå 100% CPU load.

Jeg kan ikke lige se hvordan jeg kan bruge waitformultipleobjects sammen med
den indy komponent jeg bruger, der kommer jo ingen event når der er data så
den eneste måde er vel at polle, eller hvad?
Mht. min messageloop kan jeg heller ikke se hvordan WaitForMultipleObjects
kan bruges, men MsgWaitForMultipleObjects kan måske bruges.


> * Du har et ekstra loop til sidst i din execute, der er ingen sleep, prøv
at
> fjerne det loop i første omgang.

Ja, det var bare en test jeg lavede, fejlen kommer også uden denne loop.

> * Jeg tror du risikere en deadlock situation når du bruger waitfor og
> samtidigt risikere at gå ind i dit lopp hvor du forsøger at få adgang til
> objecter på din mainform vis synchronize.

Har du en go ide til hvordan man gør det uden waitfor? Hvad med en tæller
der tæller op for hver tråd man lukker og når den så er nået til det antal
tråde man har så kaldes Close.

> * Læg dine free diverse under din mainforms OnDestroy.

Ok

>Jeg har også et par småting som intet har med dit problem at gøre
>
> I din tcp tråd glemmer du vist
> SendDataList.free? i destroy

Ups. Men sørger delphi ikke selv for at ryde op i lige den slags når man
afslutter sit program.

Mvh
HK



Henry (21-03-2004)
Kommentar
Fra : Henry


Dato : 21-03-04 16:16

Her er et eksempelt på hvordan jeg bruger det.

procedure TMainForm.CreateThreads;
begin
try
hMutex := CreateMutex(nil, false, nil);
hScheduleEvent := CreateEvent(nil, false, false, 'ScheduleEvent');
hnEvent := CreateEvent(nil, false, false, 'nEvent');

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

nThr := TnThr.create(handle);
ThreadHandelArray[0] := TnThr.handle;


except
on e:exception do LogError(lcErrorEvents ,format('Mainform.CreateThreads
%s', [e.message]));
end;
end;


procedure TMainForm.TerminateThreads;
begin
try
ScheduleThr.Terminate;
nThr.Terminate;

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

if ScheduleThr <> nil then ScheduleThr.Free;
if nThr <> nil then ScheduleThr.Free;


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

/// Aktiver et event ved at bruge

SetEvent(hScheduleEvent);

Kan bruge overalt i dit program uden at der er adgang til selven tråden,
hvis det behøves.

mvh
Henrik





Harald (21-03-2004)
Kommentar
Fra : Harald


Dato : 21-03-04 17:10

"Henry" <henry@nomail.com> skrev i en meddelelse
news:405db189$0$448$edfadb0f@dread14.news.tele.dk...
> Her er et eksempelt på hvordan jeg bruger det.
>
> procedure TMainForm.CreateThreads;
> begin
> try
> hMutex := CreateMutex(nil, false, nil);
> hScheduleEvent := CreateEvent(nil, false, false, 'ScheduleEvent');
> hnEvent := CreateEvent(nil, false, false, 'nEvent');
>
> ScheduleThr := TScheduleThr.create(handle);
> ThreadHandelArray[0] := ScheduleThr.handle;
>
> nThr := TnThr.create(handle);
> ThreadHandelArray[0] := TnThr.handle;
>
>
> except
> on e:exception do LogError(lcErrorEvents
,format('Mainform.CreateThreads
> %s', [e.message]));
> end;
> end;
>
> procedure TMainForm.TerminateThreads;
> begin
> try
> ScheduleThr.Terminate;
> nThr.Terminate;
>
> case WaitForMultipleObjects(2, @ThreadHandelArray[0], true, 20000) of
> WAIT_TIMEOUT : begin
> LogError(lcErrorEvents,'MainForm.TerminateThreads WAIT_TIMEOUT');
> end;
> end;
>
> if ScheduleThr <> nil then ScheduleThr.Free;
> if nThr <> nil then ScheduleThr.Free;
>
>
> closeHandle(hMutex);
> closeHandle(hScheduleEvent);
> closeHandle(hnEvent);
> except
> on e:exception do LogError(lcErrorEvents, format('TerminateThreads
%s',
> [e.message]));
> end;
> end;
>
> /// Aktiver et event ved at bruge
>
> SetEvent(hScheduleEvent);
>
> Kan bruge overalt i dit program uden at der er adgang til selven tråden,
> hvis det behøves.

Men den løsning kan man vel ofte risikere at få en WAIT_TIMEOUT fordi den
ene tråd venter på adgang til MainFormen. I stedet for at bruge WaitFor har
jeg nu lavet en løsning hvor en tæller tæller op for hver gang en tråd
afslutter, når tælleren når til antallet af tråde så lukkes programmet.
Denne metode giver alle tråde fuld adgang til MainForm mens der afsluttes.

Hvad bruger du din Mutex og dine 2 Events til f.eks.?

Mvh
HK



Harald (21-03-2004)
Kommentar
Fra : Harald


Dato : 21-03-04 17:42

"Harald" <news10@-REMOVE-THIS-kroning.dk> skrev i en meddelelse
news:405dbe75$0$465$edfadb0f@dread14.news.tele.dk...
> "Henry" <henry@nomail.com> skrev i en meddelelse
> news:405db189$0$448$edfadb0f@dread14.news.tele.dk...
> > Her er et eksempelt på hvordan jeg bruger det.
> >
> > procedure TMainForm.CreateThreads;
> > begin
> > try
> > hMutex := CreateMutex(nil, false, nil);
> > hScheduleEvent := CreateEvent(nil, false, false, 'ScheduleEvent');
> > hnEvent := CreateEvent(nil, false, false, 'nEvent');
> >
> > ScheduleThr := TScheduleThr.create(handle);
> > ThreadHandelArray[0] := ScheduleThr.handle;
> >
> > nThr := TnThr.create(handle);
> > ThreadHandelArray[0] := TnThr.handle;
> >
> >
> > except
> > on e:exception do LogError(lcErrorEvents
> ,format('Mainform.CreateThreads
> > %s', [e.message]));
> > end;
> > end;
> >
> > procedure TMainForm.TerminateThreads;
> > begin
> > try
> > ScheduleThr.Terminate;
> > nThr.Terminate;
> >
> > case WaitForMultipleObjects(2, @ThreadHandelArray[0], true, 20000)
of
> > WAIT_TIMEOUT : begin
> > LogError(lcErrorEvents,'MainForm.TerminateThreads
WAIT_TIMEOUT');
> > end;
> > end;
> >
> > if ScheduleThr <> nil then ScheduleThr.Free;
> > if nThr <> nil then ScheduleThr.Free;
> >
> >
> > closeHandle(hMutex);
> > closeHandle(hScheduleEvent);
> > closeHandle(hnEvent);
> > except
> > on e:exception do LogError(lcErrorEvents, format('TerminateThreads
> %s',
> > [e.message]));
> > end;
> > end;
> >
> > /// Aktiver et event ved at bruge
> >
> > SetEvent(hScheduleEvent);
> >
> > Kan bruge overalt i dit program uden at der er adgang til selven tråden,
> > hvis det behøves.
>
> Men den løsning kan man vel ofte risikere at få en WAIT_TIMEOUT fordi den
> ene tråd venter på adgang til MainFormen. I stedet for at bruge WaitFor
har
> jeg nu lavet en løsning hvor en tæller tæller op for hver gang en tråd
> afslutter, når tælleren når til antallet af tråde så lukkes programmet.
> Denne metode giver alle tråde fuld adgang til MainForm mens der afsluttes.
>
> Hvad bruger du din Mutex og dine 2 Events til f.eks.?

Ok, glem det, har lige set dit eksempel.

/Hk



Henry (21-03-2004)
Kommentar
Fra : Henry


Dato : 21-03-04 16:25

Hej Harald

Her er et eksempel på hvad jeg mener.

{---------------------------------------------------------------------------
--
Unit Name: thScheduler
Author: HEN
Purpose:
History:
----------------------------------------------------------------------------
-}
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
protected
procedure Execute; override;
Procedure Schedule;
public
constructor create(AhCaller : THandle);
destructor Destroy; override;
procedure StartPeriodicTimer(IntervalInSecs : Int64);
procedure StopPeriodicTimer;
procedure Terminate;
end;

implementation

{---------------------------------------------------------------------------
--
Procedure: TScheduleThr.create
Author: HEN
Date: 21-mar-2004
Arguments: AhCaller : THandle
Result: None
----------------------------------------------------------------------------
-}
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
Author: HEN
Date: 21-mar-2004
Arguments: None
Result: None
----------------------------------------------------------------------------
-}
procedure TScheduleThr.Terminate;
begin
// cancel the INFINITE waiting
SetEvent(hTerminateScheduleThread);
inherited Terminate;
end;


{---------------------------------------------------------------------------
--
Procedure: TScheduleThr.StartPeriodicTimer
Author: HEN
Date: 21-mar-2004
Arguments: IntervalInSecs : Int64
Result: None
----------------------------------------------------------------------------
-}
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
Author: HEN
Date: 21-mar-2004
Arguments: None
Result: None
----------------------------------------------------------------------------
-}
procedure TScheduleThr.StopPeriodicTimer;
begin
LogError(lcThreadEvents, 'TScheduleThr.StopPeriodicTimer');
CancelWaitableTimer(hTimer);
end;

{---------------------------------------------------------------------------
--
Procedure: TScheduleThr.Destroy
Author: HEN
Date: 21-mar-2004
Arguments: None
Result: None
----------------------------------------------------------------------------
-}
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
Author: HEN
Date: 21-mar-2004
Arguments: None
Result: None
----------------------------------------------------------------------------
-}
Procedure TScheduleThr.Schedule;
var
OldPrinter : string;
adp, ae : boolean;
OldPeriodOfDay : TPeriodOfDay;
hArray : array[0..1] of thandle;

begin
try
hArray[0] := hMutex;
hArray[1] := hTerminateScheduleThread;
LogError(lcThreadEvents,'TScheduleThr.Schedule Waiting for hMutex');
case WaitForMultipleObjects(2,@hArray[0], false, INFINITE) of
WAIT_OBJECT_0 :
try
LogError(lcThreadEvents,'TScheduleThr.Schedule got hMutex');
if terminated then exit;
postmessage(hCaller, WM_SCHEDULER_STARTED, 0, 0);

// her har jeg haft kald til de egentlige procedure (fjernet)
finally
LogError(lcThreadEvents,'TScheduleThr.Schedule releasing
hMutex');
ReleaseMutex(hMutex);
postmessage(hCaller, WM_SCHEDULER_DONE, 0, 0);
end; // try

end; // case WaitForSingleObject(hMutex, ) of
except
on e:exception do LogError(lcErrorEvents, format('TScheduleThr.Schedule
%s',[e.message]));
end;
end;

{---------------------------------------------------------------------------
--
Procedure: TScheduleThr.Execute
Author: HEN
Date: 21-mar-2004
Arguments: None
Result: None
----------------------------------------------------------------------------
-}
procedure TScheduleThr.Execute;
var
hArray : Array[0..2] of THandle;
begin
try

hArray[0] := hTimer; // En timer kan starte ekseveringen
hArray[1] := hScheduleEvent; // Et event et andet sted i appl. kan
starte ekseveringen
hArray[2] := hTerminateScheduleThread; // Et kald til terminate, giver
et event som afsluter execute
LogError(lcThreadEvents, 'TScheduleThr.Execute waiting for events');
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('TAlarmScannerThr.Execute %s',[e.message]));
end;
end;

end.




Harald (21-03-2004)
Kommentar
Fra : Harald


Dato : 21-03-04 17:41

"Henry" <henry@nomail.com> skrev i en meddelelse
news:405db3cc$0$515$edfadb0f@dread14.news.tele.dk...
> Hej Harald
>
> Her er et eksempel på hvad jeg mener.
>
>
{---------------------------------------------------------------------------
> --
> Unit Name: thScheduler
> Author: HEN
> Purpose:
> History:
> --------------------------------------------------------------------------
--
> -}
> 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
> protected
> procedure Execute; override;
> Procedure Schedule;
> public
> constructor create(AhCaller : THandle);
> destructor Destroy; override;
> procedure StartPeriodicTimer(IntervalInSecs : Int64);
> procedure StopPeriodicTimer;
> procedure Terminate;
> end;
>
> implementation
>
>
{---------------------------------------------------------------------------
> --
> Procedure: TScheduleThr.create
> Author: HEN
> Date: 21-mar-2004
> Arguments: AhCaller : THandle
> Result: None
> --------------------------------------------------------------------------
--
> -}
> 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
> Author: HEN
> Date: 21-mar-2004
> Arguments: None
> Result: None
> --------------------------------------------------------------------------
--
> -}
> procedure TScheduleThr.Terminate;
> begin
> // cancel the INFINITE waiting
> SetEvent(hTerminateScheduleThread);
> inherited Terminate;
> end;
>
>
>
{---------------------------------------------------------------------------
> --
> Procedure: TScheduleThr.StartPeriodicTimer
> Author: HEN
> Date: 21-mar-2004
> Arguments: IntervalInSecs : Int64
> Result: None
> --------------------------------------------------------------------------
--
> -}
> 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
> Author: HEN
> Date: 21-mar-2004
> Arguments: None
> Result: None
> --------------------------------------------------------------------------
--
> -}
> procedure TScheduleThr.StopPeriodicTimer;
> begin
> LogError(lcThreadEvents, 'TScheduleThr.StopPeriodicTimer');
> CancelWaitableTimer(hTimer);
> end;
>
>
{---------------------------------------------------------------------------
> --
> Procedure: TScheduleThr.Destroy
> Author: HEN
> Date: 21-mar-2004
> Arguments: None
> Result: None
> --------------------------------------------------------------------------
--
> -}
> 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
> Author: HEN
> Date: 21-mar-2004
> Arguments: None
> Result: None
> --------------------------------------------------------------------------
--
> -}
> Procedure TScheduleThr.Schedule;
> var
> OldPrinter : string;
> adp, ae : boolean;
> OldPeriodOfDay : TPeriodOfDay;
> hArray : array[0..1] of thandle;
>
> begin
> try
> hArray[0] := hMutex;
> hArray[1] := hTerminateScheduleThread;
> LogError(lcThreadEvents,'TScheduleThr.Schedule Waiting for hMutex');
> case WaitForMultipleObjects(2,@hArray[0], false, INFINITE) of
> WAIT_OBJECT_0 :
> try
> LogError(lcThreadEvents,'TScheduleThr.Schedule got hMutex');
> if terminated then exit;
> postmessage(hCaller, WM_SCHEDULER_STARTED, 0, 0);
>
> // her har jeg haft kald til de egentlige procedure (fjernet)
> finally
> LogError(lcThreadEvents,'TScheduleThr.Schedule releasing
> hMutex');
> ReleaseMutex(hMutex);
> postmessage(hCaller, WM_SCHEDULER_DONE, 0, 0);
> end; // try
>
> end; // case WaitForSingleObject(hMutex, ) of
> except
> on e:exception do LogError(lcErrorEvents,
format('TScheduleThr.Schedule
> %s',[e.message]));
> end;
> end;
>
>
{---------------------------------------------------------------------------
> --
> Procedure: TScheduleThr.Execute
> Author: HEN
> Date: 21-mar-2004
> Arguments: None
> Result: None
> --------------------------------------------------------------------------
--
> -}
> procedure TScheduleThr.Execute;
> var
> hArray : Array[0..2] of THandle;
> begin
> try
>
> hArray[0] := hTimer; // En timer kan starte ekseveringen
> hArray[1] := hScheduleEvent; // Et event et andet sted i appl. kan
> starte ekseveringen
> hArray[2] := hTerminateScheduleThread; // Et kald til terminate, giver
> et event som afsluter execute
> LogError(lcThreadEvents, 'TScheduleThr.Execute waiting for events');
> 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('TAlarmScannerThr.Execute %s',[e.message]));
> end;
> end;
>
> end.

Hvis jeg vil bruge noget ligende i min TCP tråd er jeg nok nød til at
benytte en TCP komponent der kan give en event når der ankommer data, Indy
komponenten som jeg bruger nu har ikke andre muligheder end at polle (så hut
jeg kan se).
I min SQL tråd som ikke laver andet end at vente på besked fra MainFormkan
jeg bruge metoden, i øjeblikket benytter jeg SendThreadMessage fra MainForm
og polling metoden i tråden.

Jeg takker for et godt eksempel som jeg vil gemme og læse igennem mange
gange endnu indtil metoden er inde på rygraden

Mvh
HK



Henry (21-03-2004)
Kommentar
Fra : Henry


Dato : 21-03-04 18:08


> Hvis jeg vil bruge noget ligende i min TCP tråd er jeg nok nød til at
> benytte en TCP komponent der kan give en event når der ankommer data, Indy
> komponenten som jeg bruger nu har ikke andre muligheder end at polle (så
hut
> jeg kan se).
> I min SQL tråd som ikke laver andet end at vente på besked fra MainFormkan
> jeg bruge metoden, i øjeblikket benytter jeg SendThreadMessage fra
MainForm
> og polling metoden i tråden.
Personligt bruger jeg TurboPowers kommunikations suite, det er nu frigivet
som opensource (jeg har brugt den siden midt 90) og der er nogle gode
eventbaserede komponenter til TCP kommunikation.

> Jeg takker for et godt eksempel som jeg vil gemme og læse igennem mange
> gange endnu indtil metoden er inde på rygraden
Velbekommen.

mvh
Henry



Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408186
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste