Reputation: 113
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
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
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
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