Long story short, I need a precise timer in .Net - with prescision in milliseconds - meaning, if I tell it to fire an event when 10ms passes, it must do so, +-1ms. The built-in .Net Timer class has a precision of +-16ms it seems, which is unacceptable for my application.
I found this article http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer which provides a code for a timer that is exactly what I need (even more - that has precision in microseconds).
However, problem is, the OnTimer equivalent seems to be executed in another thread. So, if I add some code that does, say:
label1.Text = "Hello World";
I will get an exception, and thus I will have to actually write it like this:
Invoke( new MethodInvoker(() =>{label1.Text = "Hello World";}));
This is, from what I understand, because the OnTimer event is fired from the timer's thread - where time is passed until enough has passed to be over the Interval, and then next OnTimer event is fired. The .Net Timer does not have such a problem - in OnTimer of the .Net Timer, I can freely modify controls's members.
Question: What should I change so that my timer will run it's OnTimer event in the main thread? Is adding "Invoke" the only choice?
You just need a fan and two plastic soda bottles to make this air conditioner. Modify the bottles by cutting off the end and punching holes in the sides. Then strap them to the back of the fan and fill the bottles with ice. Voila!
Create a cooling cross-breeze by positioning a fan across from an open window. If you're using a window box fan, it should blow into your room at the coolest hours of the day and outward during the warmest hours of the day.
While there are several ways of going about it, the one that I would generally prefer is to have the timer capture the value of SynchronizationContext.Current
when it is created. That value will, when in the UI thread, contain the current synchronization context which can be used to execute methods in the message loop when in a UI context. This will work for winforms, WPF, silverlight, etc. All of those paradigms set a synchronization context.
Just grab that value when the timer is created, assuming it's created in the UI thread. If you want have an optional constructor/property to set the value so that you can use it even if the timer isn't created in the UI thread you can, although that shouldn't be needed most of the time.
Then just use the Send
method of that context to fire the event:
public class Timer
{
private SynchronizationContext syncContext;
public Timer()
{
syncContext = SynchronizationContext.Current;
}
public event EventHandler Tick;
private void OnTick()
{
syncContext.Send(state =>
{
if (Tick != null)
Tick(this, EventArgs.Empty);
}, null);
}
//TODO other stuff to actually fire the tick event
}
There's no way around dispatching UI Element access to the main thread. If updating a UI element is really the only thing that you intend to do in the timer callback then forget about about your timer precision requirement. The user won't see the difference between 16ms and 50ms.
Otherwise carry out the time critical work in your timer callback and dispatch the rest of the UI work to the main thread:
void OnTimer()
{
// time critical stuff here
Invoke( new MethodInvoker(() =>{label1.Text = "Hello World";}));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With