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

时间:2015-07-27 13:18:08

标签: c# multithreading

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

}

2 个答案:

答案 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);
        }
    }
}