Reputation: 151
I am having problems converting my DispatcherTimer syntax to the Thread Timer. When i run my application suddenly it shuts down without any error.
Basically i want the timer to execute 2 methods every 5 seconds.
EDIT: The 2 methods are updating the UI. I am trying to attempt to get rid of the DispatcherTimer because i have to much freezes and delays in the UI display.
Dispatcher timer code:
timerW = new DispatcherTimer();
timerW.Tick += new EventHandler(timerW_Tick);
timerW.Interval = new TimeSpan(0, 0, 5000);
timerW.Start();
private void timerW_Tick(object sender, EventArgs e)
{
DisplayWegingInfo();
CaculateTimen();
}
Code for the System.Threading Timer:
public void InitializeDispatcherTimerW()
{
TimerCallback callback = MyTimerCallBack;
timerW = new Timer(callback);
timerW.Change(0, 5000);
}
private void MyTimerCallBack(object state)
{
DisplayWegingInfo();
CaculateTime();
}
Thanks.
Upvotes: 4
Views: 4843
Reputation: 33379
Judging by the name DisplayWedgingInfo, I would guess this method updates the UI? System.Threading.Timer executes on a thread that is different than the UI thread, so to be able to update the UI from that thread you would need to marshal those calls back to the Dispatcher
thread using Dispatcher::[Begin]Invoke
.
So you can leave whatever expensive work that doesn't touch UI elements as is, but for the UI manipulation you would simply do:
string someValue = this.SomeExpensiveOperation();
this.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
this.myControl.Text = someValue;
}));
I should point out that there will be some interruption to any UI interaction/rendering that might be going on when the invocation does occur. This is unavoidable as the execution will happen on the main thread. By using DispatcherPriority.Background
you at least schedule the update with a priority that keeps it lower than any input that the user might be providing at the time. However, don't expect to be able to make a massive update to the UI without any penalty. If you need to do this it's best to queue up multiple invocations with Background
priority so that they can happen with higher priority stuff like input in between if necessary.
Upvotes: 2
Reputation: 21743
I would check for 2 things: 1. As some others have said, make sure that if you are updating the UI, that you are Invoking back to the dispatcher -- you can only update the UI from the UI thread. Even if you are using databinding -- if a timer thread updates a value that is databound to the UI, that "counts" as the wrong thread touching the UI.
Upvotes: 0
Reputation: 21241
I think you need to separate your data retrieval/calculation from your data display.
As Daniel points out, any GUI updating needs to be done on the Dispatcher thread, so the easiest way is to use DispatcherTimer
.
However, using DispatcherTimer
means that everything in your timer callback gets done in the GUI thread. This is not good if you have any operations that take an appreciable amount of time. The GUI will stutter and lock up as you have found.
You need to work out what is taking the time. From your other question I would guess that it is the SQL retrieval. In this case you would be better doing the actual retrieval on a separate thread (by using System.Threading.Timer
) and once you have the result, update the display by using Dispatcher.BeginInvoke()
to marshal to the GUI thread.
Upvotes: 0
Reputation: 174279
The problem most likely is that you are updating your UI in the methods in your timer callback. This is only possible from the UI thread and the timer runs in a background thread.
I suggest you stick with the DispatcherTimer
.
An alternate solution would be to split the code up a bit: Extract the work intensive code into other methods and run them in a background thread and update the UI afterwards from the UI thread.
Something like this:
private void MyTimerCallBack(object state)
{
LongCalculationsThatDontNeedTheUI();
_dispatcherUIThread.Invoke(new Action(UpdateUI));
}
Upvotes: 3
Reputation: 41236
Why not simply use a background thread to dispatch events?
CancellationTokenSource cts = new CancellationTokenSource();
Task.Factory.StartNew(() =>
{
while(!cts.IsCancellationRequested)
{
Thread.Sleep(5000);
this.Dispatcher.BeginInvoke(new Action(() =>
{
DisplayWegingInfo();
CalculateTimen();
}), null);
}
});
Upvotes: -3