Comparing Timer with DispatcherTimer
Windows.Forms.Timer
uses the windows forms message loop to process timer events. It should be used when writing timing events that are being used in Windows Forms applications, and you want the timer to fire on the main UI thread.
DispatcherTimer
is the WPF timing mechanism. It should be used when you want to handle timing in a similar manner (although this isn't limited to a single thread - each thread has its own dispatcher) and you're using WPF. It fires the event on the same thread as the Dispatcher.
In general, WPF == DispatcherTimer
and Windows Forms == Forms.Timer
.
That being said, there is also System.Threading.Timer
, which is a timer class
that fires on a separate thread. This is good for purely numerical timing, where you're not trying to update the UI, etc.
Performance for Timer vs DispatcherTimer
After some more research and analysis, I've come to the conclusion that a regular timer works best in my made-up example. So far, I haven't had to look out for anything specific that would cause potential problems in my code. Having said that, good coding practices never hurt!
DispatcherTimer vs a regular Timer in WPF app for a task scheduler
DispatcherTimer is the regular timer. It fires its Tick event on the UI thread, you can do anything you want with the UI. System.Timers.Timer is an asynchronous timer, its Elapsed event runs on a thread pool thread. You have to be very careful in your event handler, you are not allowed to touch any UI component or data-bound variables. And you'll need to use the lock statement where ever you access class members that are also used on the UI thread.
In the linked answer, the Timer class was more appropriate because the OP was trying to run code asynchronously on purpose.
C# WPF Dispatcher Timer Tick in Separate Thread
Make the Tick handler async and await the long-running call:
private async void dispatcherTimer_Tick(object sender, EventArgs e)
{
await Task.Run(() =>
{
// make query here
});
// update the UI outside the Task
_notifyIcon.Text = "Current Issues: " + output;
}
Even better would be to directly call async methods, like
private async void dispatcherTimer_Tick(object sender, EventArgs e)
{
...
dataReader = await command.ExecuteReaderAsync();
...
}
Efficiency of DispatcherTimer versus Thread.Sleep
The DispatcherTimer
will invoke a method on your UI thread every N [unit of time]. Thread.Sleep
will actually sleep the thread completely. The difference is that with the former, the thread continues, then invokes the Tick
event and the latter stops the Thread from doing anything.
It's important to realise that the UI Thread is busy rendering the UI and running your code; hence, a sleep in the UI thread will be perceived as an application hang.
Date comparison within timer
You only compare the times every second - the milliseconds will still be different (especially assuming the turn-on time you compare to most likely doesn't use milliseconds). To compare in a second resolution you could do something like this:
DateTime currentTime = DateTime.Now;
currentTime = currentTime.AddMilliseconds(-currentTime.Millisecond);
Issue with DispatcherTimer for a Countdown clock
Do not subscribe to the DispatcherTimer
every time you call CountDown
.
DispatcherTimer timeLeft;
int timesTicked = 60;
public QuickPage()
{
timeLeft = new Dispatcher();
timeLeft.Tick += timeLeft_Tick;
timeLeft.Interval = new TimeSpan(0,0,0,1);
}
private void QuestionGenerator()
{
timeLeft.Start();
if (iAsked < 6)
{
//Code to generate random question
}
}
Dispatch timer won't work
You need to fix the event handler signature. It's missing the sender and the type of the second parameter is just object
. (See the documentation.)
void timer_Tick(object sender, object e)
{
TimeRefresh();
}
You also need to add a using Windows.UI.Xaml;
to the top of your class, or instantiate the timer using the full namespace:
Windows.UI.Xaml.DispatcherTimer timer = new Windows.UI.Xaml.DispatcherTimer();
If anyone stumbles on this and is using WPF, it has it own DispatchTimer. Make sure you're referencing "WindowsBase" (should be there by default). The signature is slightly different.
void timer_Tick(object sender, EventArgs e)
{
TimeRefresh();
}
The namespace it lives in is different too. Either add using System.Windows.Threading;
to the top, or qualify with the full namespace:
System.Windows.Threading.DispatcherTimer timer
= new System.Windows.Threading.DispatcherTimer();
If you're using WinForms, you want to use a different timer. Read this for the difference between the WinForms Timer and the WPF DispatchTimer.
Related Topics
C# How to Loop While Mouse Button Is Held Down
Dataview.Sort - More Than Just Asc/Desc (Need Custom Sort)
Determining If File Exists Using C# and Resolving Unc Path
Persist Data by Programming Against Interface
Generic Type Conversion from String
What Exactly Is an Assembly in C# or .Net
How to Loop Through a List<T> and Grab Each Item
C# - Volatile Keyword Usage VS Lock
Is There Any Connection String Parser in C#
Should I Unsubscribe from Events
Convert Int to a Bit Array in .Net
Attempted to Read or Write Protected Memory
Processinfo and Redirectstandardoutput
The Type Arguments for Method Cannot Be Inferred from the Usage
Initial Capacity of Collection Types, E.G. Dictionary, List
Who Should Call Dispose on Idisposable Objects When Passed into Another Object