There is a simple WinForms application. In the window is the ListBox component to which the item should be added periodically. It also displays intermittently MessageBox. It is done using System.Timers.Timer.

namespace TestWindowsFormsApplication { public partial class Form1 : Form { System.Timers.Timer timer = new System.Timers.Timer(1000); private int i = 0; delegate void GUIUpdate(int numb); void DoGUIUpdateListBox(int n) { if (this.InvokeRequired) { GUIUpdate d = new GUIUpdate(this.DoGUIUpdateListBox); this.BeginInvoke(d, n); } else listBox1.Items.Add(n); } public Form1() { InitializeComponent(); button1.Text = "Нажмите, чтобы начать"; timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); } void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { System.Windows.Forms.MessageBox.Show("i = " + i + "\r\n" + DateTime.Now.Second + ":" + DateTime.Now.Millisecond, "Timer Event Raised!"); DoGUIUpdateListBox(i); i++; } private bool begin = false; void button1_Click(object sender, EventArgs e) { if (!begin) { begin = true; button1.Text = "Закончить добавление"; timer.AutoReset = true; timer.Start(); } else { begin = false; button1.Text = "Начать добавление"; timer.Stop(); } } } } 

But the timer handler calls only Message. Show, and then it doesn't work, the elements are not displayed, the variable is not incremented, how to do it correctly?

  • one
    Everything works for me, but it works correctly only if you click on OK on MessageBox`e - Yaroslav Schubert
  • I need, for example, everything to be done synchronously - kosig
  • What do you mean by "synchronously" in this case. If you just need DoGUIUpdateListBox (i) to be called anyway and the variable is incremented, then look at my answer, if not, please explain in more detail. - Yaroslav Schubert
  • Yes. just like in your example. The actual message boxes are not needed, I just need to add items to the ListBox. but decided to add a messagebox and here. Why it happens? Call MessageBox'a takes one of the timer threads to show the window and stops there? - kosig
  • Each call to MessageBox.Show creates a new thread and waits for the user to make a decision (accept / close). - Yaroslav Schubert

3 answers 3

  void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { DoGUIUpdateListBox(i); System.Windows.Forms.MessageBox.Show("i = " + i++ + "\r\n" + DateTime.Now.Second + ":" + DateTime.Now.Millisecond, "Timer Event Raised!"); // i++; } 

DoGUIUpdateListBox(i); before calling the Messagebox and did i ++ inside the call to MessageBox.Show and everything works fine

    This is due to the fact that you access the form from another thread, you can fix it through Invoke:

     void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { System.Windows.Forms.MessageBox.Show("i = " + i + "\r\n" + DateTime.Now.Second + ":" + DateTime.Now.Millisecond, "Timer Event Raised!"); Invoke(new Action(()=>{DoGUIUpdateListBox(i);}); i++; } 
    • Your example works similarly to the author’s method. Until the MessageBoxʻa dialog box is closed, the call to System.Windows.Forms.MessageBox.Show will not go further. - Yaroslav Schubert
    • Misunderstood means. I thought it was obvious that messaging boxing was not asynchronous. You can then insert the box on the message box: Invoke (new Action (() => {System.Windows.Forms.MessageBox.Show ("i =" + i + "\ r \ n" + DateTime.Now. Second + ": "+ DateTime.Now.Millisecond," Timer Event Raised! ");})); just if flow problems arise, then he will swallow them quietly, will not throw them out (will rather throw them out, but it will come and the stream will not be known to anyone :-)) - Chad
    • so it doesn't work either. And it seems like I am working in DoGUIUpdateListBox through BeginInvoke. - kosig
    • else listBox1.Items.Add(n); - this is not through an invok, but in the timer thread is executed .... - Chad

    The problem is that the MessageBox call is blocking, so the timer_Elapsed method waits until you close the dialog.

    Your code is redundantly complex for such a simple task. To avoid messing with InvokeRequired , apply the native System.Windows.Forms.Timer :

     var timer = new System.Windows.Forms.Timer(); timer.Interval = 1000; int n = 0; timer.Tick += (o, args) => listBox1.Items.Add(n++); timer.Start();