I am writing a home WPF app that is obtaining a file from a server at a configured interval.
It’s a basic window, with a couple of labels. I have the following
- Start Time (reflects DateTime the “Start” event was hit
- Duration (reflects the time the app has been running)
- Speed (the download speed of the file)
I want to update the Duration on the Main window each second so I have the following code to do this (in a seperate class “RunDownloader.cs”).
private void StartTickTimer()
{
const double interval = 1000;
if (_tickTimer == null)
{
_tickTimer = new Timer
{
Interval = interval
};
_tickTimer.Elapsed += _ticktimer_Elapsed;
}
_tickTimer.Start();
}
On _ticktimer_Elapsed I call a method in the main window _mainWindow.UpdateTicker();
This does the following.
public void UpdateTicker()
{
var timeStarted = lblTimeStarted.Content.ToString();
DateTime startTime = DateTime.Parse(timeStarted);
TimeSpan span = DateTime.Now.Subtract(startTime);
//ToDo: Output time taken here!
//lblTimeElapsed.Content =
}
I have two issues.
-
I have the following exception when calling lblTimeStarted.Content.ToString(); in UpdateTicker()
"The calling thread cannot access this object because a different thread owns it." -
I dont quite know, how to show the duration correctly for lblTimeElapsed.Content from TimeSpan
Thanks in advance for any answers. 😀
In WPF you cannot update UI objects (that get created on the UI thread) from threads other than the UI thread.
In order to update UI controls from some other thread (eg a timer thread) you need to use the Dispatcher to run your update code on the UI thread.
This Question/answer may help you or you will find plenty of info by googling “WPF Dispatcher”.
An example dispatcher call – the lamda code will get posted off to run on the UI thread:
Alternatively you could replace your existing timer with a DispatchTimer – unlike the timer you are using it ensures that the timer callback is on the UI thread: