Probleme mit Timer

26/07/2008 - 14:29 von Nicolas Pavlidis | Report spam
Hi!

Sorry für das generische Subject, das problem is irgednwie schwer auf
ein sprechendes Subject zu birngen.

Folgendes würde ich gerne modelieren:

Ich habe ein paar Controler, die lesen Werte von irgendwo Werte ein.
Das Problem ist, dass manche Controler (sind alles Objekte) öfter lesen
sollen als andere.

So ich hab mir zum Modelieren dieses problems zwei Varianten ausgedacht:

Variante 1:

Es gibt einen ControlerUpdater wo die ganzen Controlers regestriert
werden und ihnen ein Updateintervall zugewiesen wird, im endeffekt ein
Dictionary<Int32, List<Controler>>. Dieser Updater hat weiters eienn
Timer, der alle 100 Milliseconden ein Elapsed - event auslöst und die
Zeitspanne seit dem ersten Event in einem priviate meber in dieser
Klasse (ControlerUpdater) speichert. Ich barauch die Zeitspanne in
Millisecunden, da die einzelnen Controelr ja intervallsmàsig ein Update
ihrer Werte machen sollen.

Gut zu erst habe ich dem Timer zugertraut dass es reicht wenn ich
elapsed richtig implementiere, da der Timer selbst ja in eienm Thread
laufen sollte, war zu hoch gegriffen.

Nàchster Versuch war Den ControlerUpdater als Thread zu starten und im
ThreadStart - Delegate einfach eine Endlossschleife zu machen, wenig
schlau von mir, weil sich die beiden Thread nun gegenseitig beinflusst
haben, und der Timer seltsamerweise nicht mehr richtig tickte :-(

Ich hab auch versucht das ganze mittels Semaphoren zu syncronisieren,
sprich im Elapsed - Eventhandler wird ein release gemacht und durt wo
ich die Controler raussuche mache ich ein WaitOne()

Wobei ich mir gerade denke, dass da ein Mutex vielleicht besser wàr *schàm*.

Warum so kompliziert? naja wie gesagt ich brauche die Zeitspanne die
seit dem ersten Tick vergangen ist, und der Timer gibt diese Information
leider scheinbar nit preis :-(

Und die ganze Arbeit kann ich leider niccht im Elapsed handler machen ,w
eil sonst mein ControelrUpdater nix updaten tut :-)

BTW Es geht natürlich um System.Timers.Timer.

Jetzt frag ich mich halt wie ich dieses problem so lösen kann, dass ich
immer genau zu meineem gegebenen Zeitpunkt ein elapsed bekommen (das war
bei meinen gehverscuhen nàmlich nie 100 ms wie ich es wollte, sodnern
ein bissi drüber), oder ob ich das ganze Problem anders angehen soll.

Ich hoff ich konnte das ganze gut genug beschreiben.

Varainte 2 wàre übrigens ein simpler Sceduler mit Prioritàten, wobei
wobald der Controler sein Update gemacht hat seine Prioritàt uns ein
ernidrigt wird, und sobald sie 0 wird wieder auf den ursprünglichen Wert
gesetzt wird, so erreiche ich dass garantiert jeder drann kommt.

WÄr wohl einfacher zu implementieren als der Timer, aber interessanter
wàr der Timer halt schon :-)

Vielleicht kann mir ja jemand auf die Sprünge helfen.

Danke && LG
Nicolas
 

Lesen sie die antworten

#1 Frank Dzaebel
27/07/2008 - 11:21 | Warnen spam
Hallo Nicolas,

Ich habe ein paar Controler, die lesen Werte von irgendwo Werte ein.
Das Problem ist, dass manche Controler (sind alles Objekte) öfter lesen
sollen als andere.



In welcher Technologie denn, WPF, Windows Forms, ?
Beachte ggf., dass der "System.Windows.Forms.Timer" für
Windows Forms in der "Regel" geigneter ist (wie der Name
eigentlich schon sagt).
Aber gut, es gibt Szenarien, da benutzt man auch den "Timers.Timer",
dessen Elapsed-Handler ja aber normal nicht im UI-Thread làuft
(sondern in einem eigenen Threadpool-Thread), wenn er denn nicht
über das SynchronizingObject in diesen UI-Thread gemarshallt wurde.
Zu beachten wàre weiterhin, den Code im Elapsed-Handler
reentrant zu implementieren, wenn die Elapsed-Ausführungsdauer
die "Interval"-Zeit überschreiten kann. Auch wichtig ist, dass es nur
eine begrenzte Anzahl von Threadpool-Threads gibt und es gibt
ggf. auch Racebedingungen bzgl. der Stop-Methode. Nicht
zuletzt feuert ein "Timers.Timer" nicht in der exakten Interval-Zeit,
sondern in er [Interval + Sleep] - Zeit (Dein Problem hier wohl).



Gut zu erst habe ich dem Timer zugertraut dass es reicht wenn ich
elapsed richtig implementiere, da der Timer selbst ja in eienm Thread
laufen sollte, war zu hoch gegriffen.



Es gibt viele unterschiedliche Arten von Timern, die je nach Kontext
unterschiedlich geeignet sind.



Wobei ich mir gerade denke, dass da ein Mutex vielleicht besser wàr
*schàm*.



Wir wissen ja nicht, was genau Du da codiert hast, klar
geht u.a. ein Mutex (sogar Prozessübergreifend), aber allgemein
natürlich andere Synchronisations-Primitive. Hier ein paar Links:

[Bearbeiten von Steuerelementen aus Threads]
http://dzaebel.net/ControlInvoke.htm



Warum so kompliziert? naja wie gesagt ich brauche die Zeitspanne die
seit dem ersten Tick vergangen ist, und der Timer gibt diese Information
leider scheinbar nit preis :-(
BTW Es geht natürlich um System.Timers.Timer.



Hmm - die Zeitspanne seit dem ersten Tick - zum Beispiel,
indem Du die Werte in eine threadsichere Collection tust:

/// <summary> Threadsichere Liste der ersten Tick-Zeitpunkte von Threads.
/// Der Hash-Key ist ein System.Timers.Timer.
/// Der Hash-Value ist ein DateTime.
/// </summary>
Hashtable liste = Hashtable.Synchronized(new Hashtable());




Jetzt frag ich mich halt wie ich dieses problem so lösen kann, dass ich
immer genau zu meineem gegebenen Zeitpunkt ein elapsed bekommen (das war
bei meinen gehverscuhen nàmlich nie 100 ms wie ich es wollte, sodnern
ein bissi drüber), oder ob ich das ganze Problem anders angehen soll.



Ja, bekannt. Das ist ja aber wieder ein andere Frage, als vorher.

"Using the Worker-Thread approach the frequency of the awakenings
are not exact, and are defined as the sum of sleeping-time and
thread's execution-time."

[CodeProject: Windows Vista aware NT Service interacting with the desktop.]
http://www.codeproject.com/KB/WCF/AppWatcher.aspx

Du kannst aber die die Differenzzeit zum "Normal" im Elapsed
Handler messen und abhàngig davon davon die Interval-Eigenschaft
erhöhen oder erniedrigen. Nicht 100% trivial, da man die
Überhànge "auspendeln" muss.


ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Ähnliche fragen