Sergey
Sergey

Reputation: 113

How to use Threads in WinForms C#?

I have a question about using threads. I have an application in WinForms. I have a start button with a method. When I click on it the method starts performing and lasts for a long time. When the method is performing the Form is not active I can't even close it until the method ends. I want to make the Form active and click on another button (Stop button) to stop method performing.

    private void start_Click(object sender, EventArgs e)
    {
        StartLoading() //Some Method which performing I want to stop at any time
    }

    private void stop_Click(object sender, EventArgs e)
    {
        //Stop performing Method from start_Click
    }

I tryed to use the next code:

    private void start_Click(object sender, EventArgs e)
    {
        Thread StartThread = new Thread(StartLoading);
        StartThread.Start();
    }

    public void StartLoading() 
    {
    }

And it works. The method is performing while the Form remains active. But I don't know how to stop this thread on stop_Click event. Maye there is another way to do what I want??

Best Regards Sergey

Upvotes: 3

Views: 199

Answers (3)

Irshad
Irshad

Reputation: 3131

You can use a BackgroundWorker for this.

        private BackgroundWorker bw = new BackgroundWorker();

        public Form()
        {
            InitializeComponent();

            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        }

        private void start_Click(object sender, EventArgs e)
        {
            if (!bw.IsBusy)
            {
                bw.RunWorkerAsync();
            }
        }
        private void stop_Click(object sender, EventArgs e)
        {
            if (bw.WorkerSupportsCancellation)
            {
                bw.CancelAsync();
            }
        }
        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            StartLoading(); //Some Method which performing I want to stop at any time
        }
        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                //"Canceled!";
            }

            else if (e.Error != null)
            {
                //"Error: " + e.Error.Message);
            }

            else
            {
                //"Done!";
            }
        }

Upvotes: 1

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

If you want a slow action to be executed until it is finished or until you manually cancel it, you may want to use Task and CancellationToken. For me it seems like the most proper way to do this:

public class MyForm
{
    private CancellationTokenSource cts = new CancellationTokenSource();
    private Task task;

    private void buttonStart_Click(object sender, EventArgs e) 
    {
        buttonStart.Enabled = false;
        buttonCancel.Enabled = true;

        task = Task.Factory.StartNew(() => {
            // do something extremely slow
            // and use 'ThrowIfCancellationRequested'

            for (int i = 0; i < Int32.MaxValue; i++)
            {
                Thread.Sleep(10);
                cts.Token.ThrowIfCancellationRequested();
            }
        }, cts.Token).ContinueWith(t => {
            if (t.IsCanceled)
            {
                // User has cancelled loading
            }
            if (t.IsFaulted)
            {
                // Exception has occured during loading
            }
            if (t.IsCompleted)
            {
                // Loading complete
            }
        });
    }       

    private void buttonCancel_Click(object sender, EventArgs e)
    {
        buttonStart.Enabled = true;
        buttonCancel.Enabled = false;

        cts.Cancel();
    }
}

Upvotes: 4

User2012384
User2012384

Reputation: 4919

If you're doing some looping inside the thread, I would suggest you to add a variable, like this:

In your stop button, add below:

bool isStopped = false;

And inside your loop:

while(yourCondition)
{
    if(isStopped)
       break;
}

This way, it's safer and can make sure you finish current loop

But if you would like to terminate it immediately, there's a function called Thread.Abort()

You'll have to modify the code like this:

Thread StartThread = null;
private void start_Click(object sender, EventArgs e)
{
    StartThread = new Thread(StartLoading);
    StartThread.Start();
}

public void StartLoading() 
{
    StartThread.Abort();
}

Upvotes: 2

Related Questions