Avatar billede spideren Nybegynder
08. februar 2007 - 08:04 Der er 5 kommentarer

Problemer med threads / Windows Services

Hej Alle

Jeg har et sært problem (syntes jeg selv)

Jeg har lavet en Windows Service som eneste opgave (under test) er at logge et "Hello mother" til event loggen hvert 10. sekund.

Men der bliver ikke logget hver 10. sekund, det svinger mellem 10 & 40 sekunder.

Jeg har fundet et eksempel på nette, hvor de bruger timespan, og delays, men det ser ud til der der er en fejl i det..

Opgaven lyder jeg skal have (helst en service) der spanner en thead hvert 10. sekund (skulle kunne ændres), hvordan skal jeg bygge min kode op?

Jeg har desværre ikke mulighed for at poste min kode da der er flere filer & jeg ikke ved hvordan man kan share dem her inde, men sender gerne til mail..

Håber at der er nogle der kan hjælpe!
Avatar billede alex_sleiborg Nybegynder
08. februar 2007 - 12:23 #1
Er det ikke bare og sætte en helt simpel timer på? Eller har jeg misforstået noget
Avatar billede spideren Nybegynder
08. februar 2007 - 15:06 #2
Jeg har en application som skal kunne lave flere ting på en gang.

Dette kan kun gøres via en thread, en timer er bundet til application processen.

Mens hvis man spanner en thread for hver opgave, sætter man det igang og via callback proceduren får man svar retur! Det er den eneste måde at løse problemet med at det tager mere end 10 sekunder for hver opgave..

Men da det er kritisk at min måling sker hvert 10. sec for alle skal threads bruges

Any ideas? hvorfor der er random delay på servicen??  min test server er ikke belastet
Avatar billede md_craig Nybegynder
08. februar 2007 - 21:52 #3
Der er to ting du skal lærer om her...

- Drift (Det du oplever)
- Jitter (Det du ikke kan undgå)

Drift går ud på i forhold til det du vil at din tid "drifter"...
Dvs. at der hele tiden går lidt mere end 10 sek, og din "Execution Cycle" vil langsomt skyde sig en hel periode. fx:

0
10.234
20.453
30.901
41.297
41.689
42.012

Get the point?

Jitter derimod, som også er en af de ting der ingår i overstående, men er usynlig grundet drift, kan du ikke undgå. Jitter går ud på at du aldrig vil kunne ramme dine 10 sekunder med 100% nødagtighed. Men uden drift vil du ramme inden for en nogenlunde præsision og din periode vil være nogenlunde konstant, som fx:

0
10.287
19.981
30.128
40.012
49.891
60.102

Get the point?


Jitter kan du som sagt ikke undgå, men du kan fjerne din drift.
-------------------------------------------------------------------------------------------------------

Den måde du ønsker at bruge tråde hvis jeg har forstået den korekt går IKKE,
da din app er tidskritisk vil dette ikke løse dit problem, der hvor det kan være en løsning at bruge tråde er at skrive til event logen, men kun kaldet til den bør ligge i en tråd selv, og intet andet. og det vil være bedst hvis det kan undgåes.
Istedet skal du sikre dig at det du ønsker udført hvert 10. Sek IKKE tager mere tid at udfører end de 10. sek, ellers kan du godt glemme det. men nu er 10 sekunder LANG tid i denne forstand, så skulle undre mig.



Det du skal nu skal bgure er en speciel timer der ikke venter 10 sek når den bliver bedt om det,
men en timer der venter til de næste 10 sekunder er gået ud fra hvornår de sidste var gået.

Den skal du ud i selv at lave så den har den funktionalitet.

Det du skal bruge (cooked down) er:

- En long til at lagre hvornår timeren sidst skulle være kaldt (lastCalled).
- En Metode, fx kaldet WaitNext( long mSec ) som venter den næste periode.
- En måde at kalde udaf til, fx som event eller også direkte implementeret (direkte er at foretrække i dit tilfælde også selv om det design messigt er det mindst praktiske)

Timeren kører på sin egen tråd og skal have højere prioritet end andre tråde i din app. WaitNext går så ud på at benytte den interne tråds sleep til at klargøre næste kald.


Timerens funktionalitet beskrevet som eksempel:

Når du nu starter din service og så din timer, så lader vi den kalde den metode der udfører dit arbejde ved tiden 0 (lige når timeren er startet)

Ud fra QueryPerformanceTimer ect. lagre vi først (før dit arbejde) hvornår dette skete. lad os bare antage at det var til tiden 0 (vil det ikke være da det vil være system tiden)
Så vi lagre 0 i "lastCalled".

Derefter udfører vi det arbejde der skal ske hvert 10 sek.
Når det er slut venter vi via Thread.Sleep(...) i 10 sek - tiden dit arbejde tog - "en lille margin".
Nu går din Thread i sleep mode indtil lige føre den skal udfører dit arbejde næste gang. i det den vågner op laver du din egen SpinWait.
Det er praktisk set en While( Nu < lastCalled + 10sek - 2ms ) , de 2 ms er en lille margin der flytter din jitter så den ikke altid rammer for sent.

I det den hopper ud af din while skal den nu starte forfra. denne gang gør vi ikke som før hvor vi fandt tiden og lagrede i lastCalled, istedet lagre vi 0 + 10 sek i lastCalled. og så kører igennem det overstående igen...
På den måde vil du kunne på en alm. windows kommer ned på kun at have Jitter og ikke Drift...

Nu er den svingning du har med 10-40 Sek dog MEGET stor, og derfor er der et eller andet sted noget som tager MEGET lang tid, dette skal identificeres, findes ud af hvorfor og så vurderes hvad man kan gøre ved...
Men du vil aldrig kunne få 100% RealTime som er det du gerne vil have, og slet ikke på et alm. Windows. med alm. Win vil du kunne komme ned på jitter på måske -/+ 500-1000 &#956;s... hvor man på RT systemer i nogle tilfælde kan komme ned på få hundrede nanosekunder.
Avatar billede spideren Nybegynder
12. februar 2007 - 20:14 #4
Hey

Tak for en god forklaring, beklager jeg ikke har svaret tilbage tidligere

men jeg ønsker ikke en while (now < (lastCalled + 10sec - timeUsed - 2ms)) det er en MEGET cpu tung metode at lave det på..

Jeg er gammel DELPHI programmør, og ved at man i DELPHI har tråde + services der virker..
Havde håbet at C# var nået samme stadie..

det er ikke 100% RT application jeg skal lave, er det acceptabelt med udsvingninger på 500ms men ikke på 25sec.. håber der er andre bud

Jeg har testet min procedure  og kan kun kun se at det tager 1sec for kaldet, men dette skulle jo være lige meget da det er en tråd..
Avatar billede md_craig Nybegynder
13. februar 2007 - 00:05 #5
Nej... det er det ikke, for det tager tid at "issue" en tråd og det er nok til at give dig drift... der ud over ser det ud til at hvertfald nogle timers i .NET venter på at din opgave afslutter (så den metode du sætter din timer til at kalde hører med)...

Drift er nu sådan set et kendt problem i alle sprog, også Delphi, C++ og C... men der er færer faktorer der spiller ind i et Unmanaged sprog som netop Delphi, C og C++ da der ikke lige pluselig starter en Garbage collecter i baggrunden, ellers har jeg faktisk set det overstående ide implementeret i C++ netop på grund af manglen. (desuden der jeg har ideen fra, er ikke min ide)...

men 25 sek er abnormalt og ser ud til at der er noget andet som pluselig går galt, evt din event log der hænger eller af anden grund.

men "while (now < (lastCalled + 10sec - timeUsed - 2ms))" er ikke meget tung CPU arbejde, det er en spinwait, meningen er jo du skal kalde sleep op til din spin wait så tæt på som muligt så den kommer til at kører så lidt som muligt, og ikke i 10 sekunder... hvis du har en spinwait på 2 ms vil du ikke mærke det.

Men hvis 500 ms udsving er acceptabelt så laver du bare en Sleep( 10000 - arbejdstid )... så skulle du være godt i land... Men igen, 25 sek er jeg overbevist om du skal finde et helt andet sted...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester