如何中止在另一个函数内启动的线程?

时间:2010-11-16 14:26:21

标签: c# multithreading

Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();

我在'Form1_Load'函数中启动一个名为't'的线程。我添加了一个按钮。单击该按钮时,线程't'应停止执行并使用这些参数创建新线程。

Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,950));
t.Start();

我知道在form_load事件中我可以使用

t.Abort();

6 个答案:

答案 0 :(得分:5)

通过使t成为表单的成员,您可以稍后在按钮单击事件处理程序中引用它。

优雅中止。 尽管t.Abort()完成了工作,但您可能会在线程t中留下半处理数据。您可以捕获线程t中的ThreadAbortException以优雅地结束处理。

注意重叠。 第二个问题是,当你的新线程已经启动时,你的线程可能还没有中止。您可以在致电t.Join()后致电t.Abort()来阻止这种情况。

希望这有帮助。

答案 1 :(得分:2)

Thread t成为您表单的私人成员。

public partial class MainForm : Form
{
    private Thread t;
}

答案 2 :(得分:1)

一种方法是使Thread t成为一个全局变量(位于Form_Load之外)。然后可以从该类中的任何方法访问和修改它。

要实例化该主题,请使用t = new Thread(....

在中止线程之前,请确保它不为空。

答案 3 :(得分:1)

您需要在需要访问它的两个位置访问Thread对象。 在这种情况下,将其作为私有变量将起作用。

e.g。

public class MyClass
{
  private Thread MyThread
  {
    get;
    set;
  }


  private void myfunc1()
  {
    MyThread = new Thread(() => moni.CurrUsage(nics,200)); 
    MyThread.Start();
  }

  private void myfunc2()
  {
    MyThread.Abort();

    //  I really need to wait until this thread has stopped...
    MyThread.Join();
  }

}

答案 4 :(得分:0)

添加已经给出的答案:

请注意,.Join()会阻止您当前的(UI)主题,让您的应用无法响应用户。

正如另一种观点:避免使用.Abort()在Monitor类中使用标志来退出正在执行的任务(如果可能)。然后,您仍然可以等待.Join(),但您可以完全控制后台线程中的状态。

public class Monitor
{
    private bool _cancel = false;

    public void Cancel()
    {
        _cancel = true;
    }

    public void CurrUsage(Nics nics, int n)
    { 
        _cancel = false;
        // ...
        while (!_cancel)
        {
        // do some stuff
        }
    }
}

在您的表格中

private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
    _monitor.Cancel()
    _t.Join()       // will return as your background thread has finished cleanly
    _t = new Thread(() => _monitor.CurrUsage(nics,950));   
    t.Start();   
}

答案 5 :(得分:0)

正如其他人所指出的,调用Abort所需的只是对线程的引用(就像.NET中的任何其他对象一样)。

<强>然而

你应该认真考虑重新考虑这种方法。通常,不鼓励调用Abort,因为它不会给目标线程提供足够的机会来达到停止点。虽然它有时是合适的(或唯一的选择),但要求目标线程停止(通常是通过volatile bool而不是像这样强迫它。

例如,

public class ThreadClass
{
    private volatile bool stopRequested;
    private Thread thread;

    public void Start()
    {
        stopRequested = false;
        thread = new Thread(ThreadMethod);

        thread.Start();
    }

    public void Stop()
    {
        stopRequested = true;

        if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not 
                                               // completed within 5 seconds
    }

    private void ThreadMethod()
    {

    }
}

然后您的代码会进入ThreadMethod。在该方法中,定期检查stopRequested的值。如果是真的,执行必要的清理(如果有的话)并优雅地退出线程。如果内容是循环,通常的做法是将检查放在循环的开头(假设循环足够紧),如果值为true,则提前退出。确切的位置实际上取决于代码,但一般的想法是应该经常检查它以使线程在设置后相当快地退出,无论何时发生。