开发者

Stop loop in class from another class

So I have two event handlers button1_Click() and button2_Click()

In button1_Click() I have something running like this:

toGet开发者_如何转开发 = textbox1.Text;
got = 0;

while (got <= toGet)
{
  //DoStuff
}

But button2_Click is supposed to be a stop button, and stop button1 early. How do I go about this? Thanks for the help. I saw this article here about it, but couldn't get it to work.


Windows.Forms answer

The least sophisticated method is this:

private bool m_stop;
private void button1_Click (object s, EventArgs ea)
{
   try
   {
   //  Don't forget to disable all controls except the ones you want a user to be able to click while your method executes.

      toGet = textbox1.Text;
      got = 0;

      while (got <= toGet)
      {
        Application.DoEvents (); 
        // DoEvents lets other events fire.  When they are done, resume.
        if (m_stop)
           break;
        //DoStuff
      }

   finally
   {
      //  Enable the controls you disabled before.
   }
}

private void button2_Click (object s, EventArgs ea)
{
   m_stop = true;
}

It has the distinct advantage of letting you execute button1_Click on the UI thread, still lets the UI respond to your stop button.

It has a disadvantage that you must protect against reentrancy. What happens if they click your button1 while button1_click is already executing!?!?

Edit: Another way I have used is to use a Timer instead of a loop. Then, the stop method just stops the timer.


As much as I understood, correct me if I'm wrong, you're on single thread. Wired, but you can check for single boolean value inside the your While loop, just as post suggested.

May be to make life easier (may be this is what "couldn't get it to work" means) is inside loop call

1) Windows Forms: Application.DoEvents()

2) WPF (little bit more tricky) : DoEvents in WPF

This to make breathe system.


You need to start the process inside the button1 in new thread, and when you press the button2 flag a local variable to false to stop the loop. like:

using System.Threading;

private volatile bool _requestStop = false;
private readonly object _oneExecuteLocker = new object();    


private void OnButton1Click(ojbect sender, EventArgs e)
{
    new Thread(() =>
    {
        if (Monitor.TryEnter(_oneExecuteLocker))
        {//if we are here that is means the code is not already running..
            try
            {
                while (!_requestStop)
                {
                    //DoStuff
                } 
            }
            finally
            {
                Monitor.Exit(_oneExecuteLocker);
            }
        }
    }){ IsBackground = true }.Start();
}

private void OnButton2Click(object sender, EventArgs e)
{
    _requestStop = true;
}

Notes:

  • When ever you want to update a UI control inside the newly created thread you should use contorl.Invoke(/*the code get/set or call method in the UI*/).
  • The Monitro.Enter is just to be sure that your code will not executed multiple time per click if it already running.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜