The callback timer closes the WPF application (DispatcherTimer works ..)

I have a WPF application with a text block displaying the current time. The specified text block is bound to DependencyProperty in the ViewModel. Naturally, I need to constantly update the time, so I used the timer (System.Threading.Timer) as follows:

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"); } 

The fact is that when the callback is called, the application exits ... bummer (the output says: "In WindowsBase.dll, the first case of an exception like" System.InvalidOperationException "occurred when it was going to write in DP Time).

If I use DispatcherTimer everything works fine. I do not mind using DispatcherTimer, it is just that the application is quite large and I would like to tune its performance as best as possible. As far as I can see, I am not getting access to the user interface thread (I just update the property), so DispatcherTimer is not needed.

Did I miss something?

Thanks.

EDIT: Properties are defined as follows:

  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("")); 

(date matches)

+4
source share
1 answer

The timer callback is executed on a thread that is not a user interface thread, which causes problems; the reason this happens despite the fact that you are β€œonly updating the property” is because such a call creates a chain of calls, namely to notify interested parties about changes to the property, which in this case is the user interface, and, consequently, an area of ​​bubbles to cause incorrect calls with cross flows.

To overcome this, you can specify the Dispatcher your Window in the timer constructor as an argument to the state parameter, then use Dispatcher.Invoke .

For instance...

 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"); } 

EDIT:

Using a DispatcherTimer , as suggested by Henk, and even considered by yourself, may well be the way to go here, however - I simply did not know about the type and therefore could not demonstrate in my answer. Regarding DispatcherTimer and performance, on what basis is your concern based?

+2
source

Source: https://habr.com/ru/post/1338252/


All Articles