Šta je novo?

Prost non-visual Timer

hwfanatic

Čuven
Učlanjen(a)
13.02.2002
Poruke
660
Poena
630
Pogledaj dole. :idea:
 
Nakon malo mozganja timer izgleda nesto drugacije...
[code:1]
TTimer = class(TThread)
private
FInterval, FIdent: Cardinal;
FEnabled: Boolean;
FTrigger: TTrigger;
procedure SetInterval(Value: Cardinal);
procedure SetEnabled(Value: Boolean);
procedure Update;
public
constructor Create;
property Interval: Cardinal read FInterval write SetInterval;
property Enabled: Boolean read FEnabled write SetEnabled;
property OnTimer: TTrigger read FTrigger write FTrigger;
procedure Execute; override;
procedure Jerk;
end;

implementation

{ TTimer }

constructor TTimer.Create;
begin
inherited Create(false);
FreeOnTerminate := true;
end;

procedure TTimer.Execute;
var
MsgStruct: TagMsg;
begin
while GetMessage(MsgStruct, 0, 0, 0)
do begin
if (MsgStruct.message = WM_TIMER) and (MsgStruct.WParam = FIdent) and Assigned(FTrigger)
then FTrigger;
end;
end;

procedure TTimer.Jerk;
begin
FInterval := 1;
FEnabled := true;
Update;
end;

procedure TTimer.SetEnabled(Value: Boolean);
begin
FEnabled := Value;
Update;
end;

procedure TTimer.SetInterval(Value: Cardinal);
begin
FInterval := Value;
Update;
end;

procedure TTimer.Update;
begin
if FEnabled
then FIdent := SetTimer(0, 0, FInterval, nil)
else if FIdent <> 0
then begin
KillTimer(0, FIdent);
Fident := 0;
end;
end;
[/code:1]
Problem je opet u obradi windowsovih poruka... Naime, ovaj thread ih upste ne dobija. Kada stavim minimalno modifikovan kod iz Execute metode u glavni program, sve radi ok, ali ovo treba da bude samostalan objekat...

Treba mi pomoc kako da prosledim dobijene poruke ovom, pa i drugim thread-ovima. U pitanju je raw api program, znaci bez formi ili prozora...

Help please :|
 
Chekaj, a zashto uopshte izvodish Timer iz TThreada?
 
Znas kako - nisam ni sam siguran. Programiranje bez formi je nesto novo za mene... Dakle, svaki konstruktivan predlog je vrlo dobrodosao! :)
 
pazi, ne znam koliko ovo zvuchi zdravorazumno, ali ja kad neshto ne znam da izvedem u delphiju, uradim u C-u... ja bih napravio DLL koji eksportuje funkciju tipa MojTimer i u njoj koristio obichan timer iz winapija... onda bih je pozivao iz Delphija...

PS. ili zashto jednostavno ne koristish TTimer? on nije vizuelna kontrola...
 
Ako mislis na naslov, pogresno sam se izrazio. :|
Inace, timer-u treba owner, od koga uzima handle i tako to... Osim ako ne znas kako da premostis to. *high hopes*
 
hwfanatic je napisao(la):
Inace, timer-u treba owner, od koga uzima handle i tako to... Osim ako ne znas kako da premostis to. *high hopes*

MojTajmer := TTimer.Create(nil);

:happy:

Taj owner mu treba samo radi kaskadnog 'ubijanja', tj. kada se ubije Owner, da se i sam timer ubije kao njegov child. Mozes da kreiras ovako, samo moras onda explicitno da oslobodis memoriju koju zauzima (kada dodje vreme za ubijanje) sa klasicnim MojTajmer.Free (ili FreeAndNil(MojTajmer) - sasvim svejedno). Ovaj TTimer inace sam obezbedi sebi svoj handle, pa mu owner za to ni ne treba.

Greska sa ovom tvojom klasom je i to sto nisi u Execute metodu sve sto radis uvezao u 'while not terminated' petlju, pa se ne vidi sta i koliko taj thread radi i kada i kako je terminisan. Rad prekidas naravno sa MojTajmer.Terminated := true;

Problem je i malo u tome sto si krenuo da nasledjujes TThread za tajmer koji je jednostavno proces niskog prioriteta. Ako ti treba komunikacija medju threadovima zavisna od nekog taminga (recimo periodicna), neki pravilniji pristup bi bio sledeci:
1. napravi thread klasu, tzv 'radilicu' - to je klasa ciji objekti paralelno izvrsavaju isti tip posla - recimo paralelnu komunikaciju preko socketa sa vise IP adresa
2. napravi thread klasu tzv 'sinhronizator', ciji ce objekat sinhronizovati threadove radilice i davati im potrebne podatke kada sta da urade
3. za komunikaciju medju threadovima ti trebaju definisani eventovi. Ali ne eventovi u smislu metoda klase, nego eventovi kao klase izvedene iz TEvent klase. Ako pratim primer sa ovom komunikacijom, recimo da imam jedan event Heartbeat koji salje svima u mrezi broadcast ping signal (dakle, HeartBeat = class(TEvent);).
4. uzmi jednu varijablu tipa TTimer.

U tajmeru definisi periodicnost i da kod okidanja daje neki signal sinhronizacionom threadu (recimo inkrement nekog static countera - obicno critical section objekat) kojem ce pristupati samo taj thread radi citanja i na taj nacin ce citanje biti sigurno. Kada taj sinhroni thread utvrdi da je tajmer okinuo jedan podeok (u svojoj Execute proceduri u 'While not terminated' petlji), on okida taj HeartBeat event. Ovi drugi threadovi 'radilice' u svojoj Execute proceduri imaju HeartBeat.WaitFor petlju i kada detektuju da je iz sinhronizacionog threada okinut event, oni ce uraditi ono sta treba (stoji obicno unutar te Heartbeat.Waitfor($FFFFFFFF) = wrSignaled petlje).
Ukoliko ti je potreba za razlicitim eventovima, ti ih definisi i okidaj lepo.
 
silverglider je napisao(la):
MojTajmer := TTimer.Create(nil);
Osecam se mnogo glupo. :|

Ali, svejedno, tajmer nije hteo da radi dok nisam stavio ovo u glavni program:
[code:1]
function Terminated: Boolean;
var
MsgStruct: TagMsg;
begin
Result := false;
if GetMessage(MsgStruct, 0, 0, 0) and (MsgStruct.message = WM_QUIT)
then Result := true;
DispatchMessage(MsgStruct);
end;

begin
while not Terminated
do;
end;
[/code:1]
Bez dispecera ne bi bilo nista. :)

A, sto se nasledjivanja od TThread-a, tu sam se malo spetljao; jednostavno nisam znao sta drugo da radim... Hvala puno na pomoci :!:
 
Prouci samo dobro upotrebu TEvent klase u helpu i to je to.

Za trigerovanje periodicnih eventova ima i drugih nacina, recimo da se napravi kombinacija TTimera i UDPclienta koji salju odredjeni record ili cak nesto jednostavnije - integer ili string - periodicno. To cak moze biti izdvojeno i u poseban programcic. Sa druge strane imas UDPserver koji 'osluskuje' na odredjenom portu i kada dodje 'telegram', startuje odredjenu akciju (moze da analizira telegram ukoliko postoji vise razlicitih vrsta telegrama za okidanje razlicitih komandi). UDPserver komponente su vec skoro sve threaded u izvedbi, pa nema ni oko toga sta da brines (indy recimo provereno jeste, samo se ukljuci property threaded).
 
Hvala silverglider, jos jedanput. Mada, meni je bio potreban najobicniji tajmer. :) Ova tvoja prica je vrlo korisna za koordinaciju vise aplikacija, ako sam dobro razumeo, ali ja ne pravim tako nesto... Btw, cini mi se da sam cak i citao o tome bas ovde, cak mislim da si ti bio autor. :)

Sta pravim? Nista posebno - jedan mali event sheduler. Mogu vam ga poslati kad zavrsim, ako vas zanima...
 
Ne, poenta je bila ta da mozes da napravis mehanizam za koordinaciju threadova takav da u buducnosti moze cak i da se izdvoji iz same aplikacije. Stvar je u tome da ne moze sve da se uradi deljenjem na threadove zbog toga sto sam OS ogranicava resurse po threadu i kod malcice veceg posla si prinudjen da multithreading prevedes na multitasking+multithreading; odnosno podelis posao na vise procesa (bilo izvrsnih, bilo biblioteka) i onda u okviru procesa delis na niti ako treba. Ovo sam bio napisao vise kao koncept posto nisi tada bio naveo sta tacno radis sa threadovia, pa da ti skratim posao.
Ovo sa UDP-om je ok i za u okviru jedne aplikacije kada threadovi treba da razmenjuju dodatne podatke, a neces da koristis neki IPC mehanizam SharedMemory tipa ili ti CriticalSection nije dovoljno dobar/sirok ili neces da koristis nesto trece tipa fajla zbog brzine.
 
Nazad
Vrh Dno