zrubi zrubi - 2 months ago 13
C# Question

How to stop loop with button

this code takes value of incremented numbers stream with random starting number. If start1 value bigger then start2 I want display corresponding line with textbox, else another line. Problem is I can stop program until the given number of cycles is not satisfied. I'm understand the reason why I can't stop it, because it is in loop and button just hangs, but not sure what is the bast way to figure out with this problem in this case.

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace XX_7_0
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{

var random = new Random();
var start1 = random.Next(0, 100);
var start2 = random.Next(0, 100);
var incrementor1 = start1 > 50 ? -1 : 1;
var incrementor2 = start2 > 50 ? -1 : 1;
var cV1 = start1;
var cV2 = start2;

for (var i = 0; i < 1000; i++)
{
if (cV1 == 101) incrementor1 = -1;
if (cV1 == 0) incrementor1 = 1;

if (cV2 == 101) incrementor2 = -1;
if (cV2 == 0) incrementor2 = 1;

if (cV1 > cV2)
{
textBox1.AppendText("ID: (" + i + ") CV1: (1): [" + cV1 + "] CV2: (0) [" + cV2 + "]\n");
}
else
{
textBox1.AppendText("ID: (" + i + ") CV1: (0): [" + cV1 + "] CV2: (1) [" + cV2 + "]\n");
}

cV1 += incrementor1;
cV2 += incrementor2;
}
}
}
}

Answer

Your code will take a minimum of 100 seconds because of each Thread.Sleep. Since the logic is run on the same thread as the GUI this will freeze up the GUI as well. You'll want to look into offloading heavy computation to a separate thread. You can use an abstraction like BackgroundWorker to make it easy for the worker thread to report its progress and when it completes. Alternatively you could use Task which was added to .NET relatively recently, and seems more convenient.

Example

Here is some minimal code that starts a task that prints "Testing" forever then cancels it after 1 second.

static void DoSomethingExpensive()
{
    while (true)
    {
        Console.WriteLine("Testing");
        Thread.Sleep(100);
    }
}

static void Main(string[] args)
{
    var source = new CancellationTokenSource();
    var task = new Task(DoSomethingExpensive, source.Token);
    task.Start();
    Thread.Sleep(1000);
    source.Cancel();
}

If your task has a return value you should use Task<T>.

Comments