我正在编写一个家庭 WPF 应用程序,它以配置的时间间隔从服务器获取文件。
这是一个基本窗口,带有几个标签。我有以下内容
- 开始时间(反射(reflect)“开始”事件被击中的日期时间
- 持续时间(反射(reflect)应用已运行的时间)
- 速度(文件的下载速度)
我想每秒更新主窗口上的持续时间,所以我有以下代码来执行此操作(在单独的类“RunDownloader.cs”中)。
private void StartTickTimer()
{
const double interval = 1000;
if (_tickTimer == null)
{
_tickTimer = new Timer
{
Interval = interval
};
_tickTimer.Elapsed += _ticktimer_Elapsed;
}
_tickTimer.Start();
}
在 _ticktimer_Elapsed 上我在主窗口中调用一个方法 _mainWindow.UpdateTicker();
这会执行以下操作。
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 =
}
我有两个问题。
调用 lblTimeStarted.Content.ToString() 时出现以下异常;在 UpdateTicker() 中
"The calling thread cannot access this object because a different thread owns it."
我不太清楚,如何从 TimeSpan 正确显示 lblTimeElapsed.Content 的持续时间
提前感谢您的任何回答。 :D
最佳答案
在 WPF 中,您不能从 UI 线程以外的线程更新 UI 对象(在 UI 线程上创建)。
为了从其他线程(例如计时器线程)更新 UI 控件,您需要使用 Dispatcher 在 UI 线程上运行更新代码。
这Question/answer可能会对您有所帮助,或者您可以通过谷歌搜索“WPF Dispatcher”找到大量信息。
调度程序调用示例 - lamda 代码将发布以在 UI 线程上运行:
Dispatcher.BeginInvoke(new Action(() =>
{
text_box.AppendText(formated_msg);
text_box.ScrollToEnd();
}));
或者,您可以将现有计时器替换为 DispatchTimer - 与您使用的计时器不同,它确保计时器回调在 UI 线程上:
Reasons for using a DispatcherTimer opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer.
关于c# - 在 Timer.Elapsed 事件上更新 MainWindow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10267956/