2

In my program i'm starting for loop using button, I want to break this for loop using another button. For example:

private void button1_Click(object sender, EventArgs e)
{
    for( int i = 0; i <  var; i++)
    {
        //doing something
    }
}

And using second button break loop,

private void button2_Click(object sender, EventArgs e)
{
    //breaking loop;
}

Need help :)

Dmitry Egorov
  • 9,542
  • 3
  • 22
  • 40
LomidzeAlex
  • 41
  • 1
  • 7

3 Answers3

6
  1. Set a flag in button2_Click() method and check it in the button1_Click()'s loop.

  2. In order to process Windows events and allow button2_Click() handle to run while iterating, add Application.DoEvents() in your loop:

bool breakLoop = false;

private void button1_Click(object sender, EventArgs e)
{
    breakLoop = false;
    for( int i = 0; i < var && !breakLoop; i++)
    {
         //doing something
         Application.DoEvents();
    }
}

private void button2_Click(object sender, EventArgs e)
{
    breakLoop = true;
}
Dmitry Egorov
  • 9,542
  • 3
  • 22
  • 40
  • 1
    @dasblinkenlight: actually, it can with the help of `Application.DoEvents()`. The latter invokes a callback from running code in the UI thread to the Windows message pump, which in turn processes newly came messages and calls appropriate event handlers including `button2_Click()`. There may be some latency in UI response depending on what `//doing something` actually does, though. – Dmitry Egorov Sep 30 '17 at 11:26
  • 1
    @DmitryEgorov The line `breakLoop = true;` in `button1_Click` is wrong. It should be `breakLoop = false;`. Please correct that. – MKR Sep 30 '17 at 11:32
0

You cannot do that, because the loop in button1_Click event handler will be holding the UI thread. Your user interface will not respond to any event, showing hourglass icon, until the loop is over. This means that button2_Click cannot be entered until button1_Click has completed.

You need to replace the long-running loop from the event handler with something that runs outside the UI thread. For example, you can use Tasks, which can be cancelled using CancellationToken (related Q&A).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Arguably it would be better to use threads and cancellation tokens in some form, rather than the Application.DoEvents(). Something like this:

private CancellationTokenSource loopCanceller = new CancellationTokenSource();

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        try
        {
            for (int i = 0; i < 100; i++)
            {
                this.loopCanceller.Token.ThrowIfCancellationRequested(); // exit, if cancelled

                // simulating half a second of work
                Thread.Sleep(500);

                // UI update, Invoke needed because we are in another thread
                Invoke((Action)(() => this.Text = "Iteration " + i)); 
            }

        }
        catch (OperationCanceledException ex)
        {
            loopCanceller = new CancellationTokenSource(); // resetting the canceller
            Invoke((Action)(() => this.Text = "Thread cancelled"));
        }
    }, loopCanceller.Token);
}

private void button2_Click(object sender, EventArgs e)
{
    loopCanceller.Cancel();
}
Avo Nappo
  • 620
  • 4
  • 9