定时器回调关闭WPF应用程序(DispatcherTimer工作..)

时间:2011-02-03 12:50:12

标签: c# .net wpf .net-4.0 timer

我有一个带有显示当前时间的文本块的WPF应用程序。所述文本块绑定到ViewModel上的DependencyProperty。当然我需要不断更新时间,所以我使用了一个定时器(System.Threading.Timer):

public MainViewModel()
{
    _dateTimer = new Timer(_dateTimer_Tick, null, 0, 60000);
}

void _dateTimer_Tick(object sender)
{
    Time = DateTime.Now.ToString("HH:mm");
    Date = DateTime.Now.ToString("D");
}

问题是,当调用回调时,应用程序退出... bummer(输出说:“在WindowsBase.dll中发生'System.InvalidOperationException'类型的第一次机会异常”就在它即将写入时间DP)。

如果我使用DispatcherTimer,一切正常。我不介意使用DispatcherTimer,它只是应用程序非常大,我想尽可能地调整其性能。据我所知,我没有访问UI线程(我只是更新属性),因此不需要DispatcherTimer。

我错过了什么吗?

感谢。

编辑: 属性定义如下:

    public string Time
    {
        get { return (string)GetValue(TimeProperty); }
        set { SetValue(TimeProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Time.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TimeProperty =
        DependencyProperty.Register("Time", typeof(string), typeof(MainViewModel), new UIPropertyMetadata(""));

(日期相同)

1 个答案:

答案 0 :(得分:2)

计时器回调正在一个不是UI线程的线程上执行,这会导致问题;尽管你只是“更新一个属性”,但这种情况发生的原因是因为这样的调用创建了一个调用链,即通知感兴趣的各方对属性的更改,在本例中是属性UI,因此,范围会引起不适当的跨线程调用。

要克服这个问题,您可以在计时器构造函数中指定Dispatcher的{​​{1}}作为Window参数的参数,然后使用state

例如......

Dispatcher.Invoke

编辑:

按照Henk的建议使用public MainViewModel() { _dateTimer = new Timer(_dateTimer_Tick, Dispatcher, 0, 60000); } void _dateTimer_Tick(object state) { ((Dispatcher)state).Invoke(UpdateUI); } void UpdateUI() { Time = DateTime.Now.ToString("HH:mm"); Date = DateTime.Now.ToString("D"); } ,甚至自己考虑,很可能是去这里的方式,但是 - 我根本不知道这种类型,因此无法证明在我的回答中。关于DispatcherTimer和表现,您的关注基于什么理由?