我希望当我点击thread.Abort()和线程完成打印标签后,它将中止。它只在完成当前作业时中止线程。感谢
namespace ThreadTest
{
public partial class Form1 : Form
{
Thread thread;
bool loop = true;
Stopwatch regularSW = new Stopwatch();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
thread = new Thread(new ThreadStart(() => threadtest()));
thread.Start();
}
private void button2_Click(object sender, EventArgs e)
{
thread.Abort();
}
public void threadtest()
{
while (loop)
{
regularSW.Start();
Thread.Sleep(5000);
regularSW.Stop();
this.Invoke(new Action(() => label1.Text += "Sleep in: " + regularSW.Elapsed + Environment.NewLine));
}
}
}
}
答案 0 :(得分:5)
Thread.Abort
是请求,操作系统和线程可以在无法中止的情况下自由忽略它。通常,Abort
不应在“按设计”方案中使用。相反,你的循环应检查是否有取消操作待定,可能是这样的:
Thread thread;
bool loop = true;
volatile bool _cancelPending = false;
Stopwatch regularSW = new Stopwatch();
//Snip... unchanged code removed for brevity.
private void button2_Click(object sender, EventArgs e)
{
_cancelPending = true;
}
public void threadtest()
{
while (loop)
{
if (_cancelPending) break;
regularSW.Start();
Thread.Sleep(5000);
regularSW.Stop();
this.Invoke(new Action(() => label1.Text += "Sleep in: " + regularSW.Elapsed + Environment.NewLine));
}
}
也许这就是您的loop
字段的目的,但我引入了另一个字段_cancelPending
,以防它出于不同的目的。
答案 1 :(得分:2)
在大多数应用程序中,不应该删除线程;当线程不再有工作要做时,它将作为其生命周期的自然部分停止。
为了实现这一点,您的代码需要发出该方法应该停止执行的信号。在.NET中,类型CancellationTokenSource
用于允许线程安全信令,应该停止操作。
然而,最突出的问题是你的主线大部分时间都在休眠。这意味着当按下取消按钮时,您必须等待线程唤醒才会注意到已请求取消。
我们可以使用取消机制来模拟线程休眠,等待一段时间,或者要求取消 - 以先发生者为准:
Thread thread;
CancellationTokenSource cts;
Stopwatch regularSW = new Stopwatch();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
thread = new Thread(new ThreadStart(() => threadtest(cts.Token)));
thread.Start();
}
private void button2_Click(object sender, EventArgs e)
{
cts.Cancel();
}
public void threadtest(CancellationToken cancellation)
{
while (!cancellation.IsCancellationRequested)
{
regularSW.Start();
// Simulate a Thread.Sleep; returns true if cancellation requested.
if (!cancellation.WaitHandle.WaitOne(5000))
{
regularSW.Stop();
this.Invoke(() => label1.Text += "Sleep in: "
+ regularSW.Elapsed
+ Environment.NewLine);
}
}
}