Why does System.Timers.Timer not update the user interface without busy?

I searched for a reason, but about every topic in stackoverflow that I could find was suggested as a reason for a busy user interface. I have very simple code, just for testing, and it just won’t update the user interface, although I’m sure that it cannot be occupied with something else:

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } static double t = 0; static double dt = 0.1; private void button1_Click(object sender, RoutedEventArgs e) { Timer timer = new Timer(5000); timer.Enabled = true; timer.Elapsed += new ElapsedEventHandler(Update); timer.Start(); } void Update(object sender, ElapsedEventArgs e) { t = t + dt; testBlock1.Text = (t).ToString(); } } 

I debugged it and set a breakpoint for updating textBlock1.Text , and it was interrupted every 5 seconds, but the user interface was never updated. As the code shows , when I move the mouse over the Button , I use to start the timer, the button shows its typical mouse-over-button animation. . Why is this happening but not updating the text?

If someone can lead me to a good topic in stackoverflow, do it and I will delete my question here, but I could not find a single topic explaining why this approach does not update the user interface, even if the user interface is not busy doing something else.

+4
source share
2 answers

For WPF you should use DispatcherTimer - Also, with the code above, I get a cross thread error, since the elapsed event occurs on a different thread, not on the UI thread .

 private void button1_Click(object sender, RoutedEventArgs e) { DispatcherTimer timer = new DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 5); timer.Tick += new EventHandler(timer_Tick); timer.Start(); } void timer_Tick(object sender, EventArgs e) { t = t + dt; txt.Text = (t + dt).ToString(); } 

EDIT

Alternatively, you can configure it on the Interface Manager with existing code like this -

 void Update(object sender, ElapsedEventArgs e) { App.Current.Dispatcher.Invoke((Action)delegate() { t = t + dt; txt.Text = (t + dt).ToString(); }); } 
+8
source

System.Timers.Timer will not return to the user interface thread by default. On Windows Forms, you can do this quite easily:

 Timer timer = new Timer(5000); timer.SynchronizingObject = this; 

... but the WPF interface elements do not implement ISynchronizeInvoke , which will prevent this from working in WPF.

You can use Dispatcher to go to the UI thread inside the handler, or you can just use DispatcherTimer to start with.

+12
source

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


All Articles