Timer just works if call MessageBox.Show()

2019-06-26 19:15发布

问题:

How is this possible? I have a timer that is called if have no network connection,as in method down:

public void Foo() {
     for (int i = 0, count = MailList.CheckedItems.Count; i < count; i++) {
         /* Check for network available connection in computer
              public bool HasConnection() {
                return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
             }       
         */
         if (!net.HasConnection()) { 
              SearchNetworkConnection.Start(); //start the timer 
         }
     }
}

and The _Tick method of Timer:

   private void SearchNetworkConnection_Tick(object sender, EventArgs e) {
            ++ATTEMPRECONNECT;

            string currentState = "attemp reconnect.."; 
            MessageBox.Show(currentState, "..", MessageBoxButtons.OK, MessageBoxIcon.Warning);

            if (ATTEMPRECONNECT >= ATTEMPRECONNECTLIMIT) {
                //do abort all process 
                SearchNetworkConnection.Stop();
            }
      }

That works oddly, just if I call the MessageBox.Show() after SearchNetworkConnection.Start().

In other words, it does not work, the Timer won't run:

if (!net.HasConnection()) { 
        SearchNetworkConnection.Start();
   }

calling MessageBox.Show(), it works fine:

if (!net.HasConnection()) { 
        SearchNetworkConnection.Start();
        MessageBox.Show("lol");
 }

if it can be useful, Foo() method run on thread.

Update

So, I think it's a little strange. I wrote a simple code for some tests. and I'm surprise,the mistake continue. The below code works fine, but if you do change the order

timer.Start();
DialogResult result = MessageBox.Show(text, caption);

to

DialogResult result = MessageBox.Show(text, caption);
timer.Start();

it does not work, the timer does not start.

public static DialogResult Show(string text, string caption,int dellay)
        {

            Timer timer = new Timer();
            timer.Interval = dellay;
            timer.Start();
            DialogResult result = MessageBox.Show(text, caption);
            timer.Tick += new EventHandler(delegate
             {
                    IntPtr handle = FindWindow(null, caption);

                    if (handle != IntPtr.Zero)
                    {
                        IntPtr hresult = SendMessage(handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

                        if (hresult == IntPtr.Zero)
                        {
                            timer.Stop();
                            timer.Dispose();
                        }
                    }
            });

            return result;
        }

回答1:

Your Timer needs a messagepump to run. MessageBox.Show() is providing one.

But you'll want to avoid messageboxes altogether (look at Systems.Diagnostsics.Debug.Print()).

You should probably take a look at other timers (System.Threading, System.Timers).


Part 2

You state that Foo() runs on a Thread. That sounds OK.
But the fact that your Windows.Forms.Timer needs a MessageBox to function means that you are somehow blocking your main thread. So your problem is not in the posted code but somewhere else.