The methods
Interrupt
and
Abort
should be used with caution as the documentation says:
Thread.Abort Method (System.Threading) | Microsoft Docs[
^]
A better approach is to let the thread end gracefully by setting a flag.
Please make sure the flag is marked by the volatile keyword.
This must be done because the flag variable is accessed by two threads which is the main thread and the thread you created yourself.
The volatile keyword tells the compiler not to optimize access to the flag variable.
This makes sure that always the most current value is available.
Please refer to
volatile - C# Reference | Microsoft Docs[
^]
Please have a look at this example:
It uses a form with two Buttons named buttonStart and buttonStop as well as a ListBox named "listBox".
The code behind looks like this:
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
private volatile bool cancel;
private Thread thread;
private delegate void AddTextDelegate(string text);
public Form1()
{
InitializeComponent();
buttonStop.Enabled = false;
}
private void ButtonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
cancel = false;
thread = new Thread(DoSomething);
thread.Start();
}
private void ButtonStop_Click(object sender, EventArgs e)
{
cancel = true;
thread.Join();
thread = null;
buttonStart.Enabled = true;
buttonStop.Enabled = false;
}
private void DoSomething()
{
var number = 0;
while (!cancel)
{
AddText($"{number++}");
Thread.Sleep(500);
}
}
private void AddText(string text)
{
if (listBox.InvokeRequired)
{
var d = new AddTextDelegate(AddText);
Invoke(d, text);
}
else
{
listBox.Items.Add(text);
}
}
}
}
The ListBox will be filled with numbers when you have clicked the Start button. The UI stays responsive.
When clicking the Stop button the cancel flag is set to true.
Make also sure not to call UI Elements directly from a different thread.
Windows Forms is not thread-safe.
You must use Invoke for this.
First you must check if the ListBox is updated from a different thread by using InvokeRequired. In this specific case InvokeRequired will return true, as you are updating the ListBox from a different thread.
You then invoke a delegate of AddText which will update the ListBox from the UI thread thus InvokeRequired will return false now.
An explanation of how to update the UI from a different thread can be found here
How to: Make thread-safe calls to Windows Forms controls | Microsoft Docs[
^]