如何在线程中的当前作业完成时中止线程

本文关键字:线程 作业 完成时 | 更新日期: 2023-09-27 18:04:48

我想当我点击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));
        }
    }
}

}

如何在线程中的当前作业完成时中止线程

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,以防它服务于不同的目的。

终止线程在大多数应用程序中都不应该这样做;当线程不再有工作要做时,它将作为其生命周期的一个自然部分而停止。

要允许这种情况发生,您的代码需要发出该方法应该停止执行的信号。在。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);
        }
    }
}