C# 如何停止线程?

C# 如何停止线程?,c#,multithreading,C#,Multithreading,嗨,伙计们,我用这样的代码开始线程: Thread[] thr; private void button1_Click(object sender, EventArgs e) { decimal value = numericUpDown2.Value; int i = 0; threads_count = (int)(value); thr = new Thread[threads_count];

嗨,伙计们,我用这样的代码开始线程:

    Thread[] thr;
    private void button1_Click(object sender, EventArgs e)
    {
        decimal value = numericUpDown2.Value;
        int i = 0;
        threads_count = (int)(value);
        thr = new Thread[threads_count];
        for (; i < threads_count; i++)
        {
            thr[i] = new Thread(new ThreadStart(go));
            thr[i].IsBackground = true;
            thr[i].Start();
        }
    }
Thread[]thr;
私有无效按钮1\u单击(对象发送者,事件参数e)
{
十进制值=numericUpDown2.值;
int i=0;
线程数=(int)(值);
thr=新线程[线程数];
对于(;i
如果我的条件变为真,如何停止所有线程(不推荐)-使用方法中止线程。此方法在线程上引发ThreadAbortException。像这样:

foreach(Thread thread in thr)
    thread.Abort();
但更好的方法是通知线程取消并让它正确完成其工作。您只需使用.Net 4任务即可完成此任务:

Task[] thr = new Task[threads_count];
var source = new CancellationTokenSource();

for (int i = 0; i < threads_count; i++)
{
    thr[i] = Task.Factory.StartNew(go, source.Token);
}

// later, when condition is met
source.Cancel();
野蛮方式(不推荐)-使用方法中止线程。此方法在线程上引发ThreadAbortException。像这样:

foreach(Thread thread in thr)
    thread.Abort();
但更好的方法是通知线程取消并让它正确完成其工作。您只需使用.Net 4任务即可完成此任务:

Task[] thr = new Task[threads_count];
var source = new CancellationTokenSource();

for (int i = 0; i < threads_count; i++)
{
    thr[i] = Task.Factory.StartNew(go, source.Token);
}

// later, when condition is met
source.Cancel();

简单的答案是使用thread Abort()方法,但是您的代码并没有真正弄清楚是什么条件


什么循环测试与条件?为什么需要中止线程?我这样问是因为可能有更好的方法来解决这个问题。简单的答案是使用thread Abort()方法,但是您的代码并没有真正说明什么条件


什么循环测试与条件?为什么需要中止线程?我在问,因为可能有更好的方法来实现这一点

如果您想知道如何优雅地终止线程,我建议您查看以下内容:


如果您想知道如何优雅地终止线程,我建议您查看以下内容:


您可以使用
CancellationToken
发出操作应停止的信号

  • 创建一个
    CancellationTokenSource
    作为您在按钮单击处理程序中初始化的类型的实例字段

  • 在后台方法中,定期检查令牌源中的
    令牌
    IsCancellationRequested
    属性,或者调用
    throwifcCancellationRequested()
    ,如果希望它在取消时只抛出异常

  • 如果要停止线程,请在令牌源上调用
    Cancel


  • 您可以使用
    CancellationToken
    发出操作应停止的信号

  • 创建一个
    CancellationTokenSource
    作为您在按钮单击处理程序中初始化的类型的实例字段

  • 在后台方法中,定期检查令牌源中的
    令牌
    IsCancellationRequested
    属性,或者调用
    throwifcCancellationRequested()
    ,如果希望它在取消时只抛出异常

  • 如果要停止线程,请在令牌源上调用
    Cancel


  • 许多答案都说要中止线程切勿中止线程,除非是紧急情况并且您正在关闭应用程序

    CLR保证其内部数据结构不会因线程中止而损坏这是CLR对线程中止做出的唯一(*)保证。它具体不保证:

    • 线程实际上将中止。螺纹会硬化,以防被终止
    • 任何不在CLR中的数据结构都不会被损坏。在关键操作的中间,线程中止可以在任意不一致的状态中留下BCL数据结构或用户数据结构。这可能会在以后神秘地使您的进程崩溃
    • 锁将被释放。中止线程可能会导致锁永久保留,也可能导致死锁,等等
    如果我不清楚的话:中止一个线程是非常危险的,只有当所有的选择都更糟糕的时候,你才应该这样做

    那么,如果您想启动一个线程,然后完全关闭它,该怎么办

    首先,不要那样做。首先不要开始一个线程。使用取消令牌启动一个
    任务
    ,当您想关闭它时,用信号通知它的取消令牌

    如果您确实需要启动线程,那么启动线程,这样就有了某种机制,主线程和工作线程可以干净、安全地通信“我希望您在这个时候干净地关闭自己”

    如果您不知道如何做到这一点,那么停止编写多线程代码,直到您学会如何做到这一点



    (*)这是一个小谎言;CLR还对线程中止和特殊代码区域(如受约束的执行区域和最终块)的交互做出某些保证。

    许多答案都说要中止线程切勿中止线程,除非是紧急情况并且您正在关闭应用程序

    CLR保证其内部数据结构不会因线程中止而损坏这是CLR对线程中止做出的唯一(*)保证。它具体不保证:

    • 线程实际上将中止。螺纹会硬化,以防被终止
    • 任何不在CLR中的数据结构都不会被损坏。在关键操作的中间,线程中止可以在任意不一致的状态中留下BCL数据结构或用户数据结构。这可能会在以后神秘地使您的进程崩溃
    • 锁将被释放。中止线程可能会导致锁永久保留,也可能导致死锁,等等
    如果我不清楚的话:中止一个线程是非常危险的,只有当所有的选择都更糟糕的时候,你才应该这样做

    那又怎样
    namespace Thread_TerminateProblem
    {    
        public partial class Form1 : Form
        {     
    
    
        private static AutoResetEvent m_ResetEvent = null;                
        private static ManualResetEvent m_ResetEvent_Thread = new ManualResetEvent(false);
        enum ServiceState { Start, Stop };
        bool flag = false;
        int x = 0;
        ServiceState _state;
        public Form1()
        {
            InitializeComponent();
        }
    
        private void btnStart_Click(object sender, EventArgs e)
        {
            flag = true;
            _state = ServiceState.Start;
            m_ResetEvent = new AutoResetEvent(true);            
            Thread t1 = new Thread(fun_Thread1);
            t1.Start();
            t1.Name = "Thread1";            
        }
    
        private void btnStop_Click(object sender, EventArgs e)
        {
            _state = ServiceState.Stop;
            m_ResetEvent.Set();           
        }
    
    
        private void fun_Thread1()
        {
            while (true)
            {                               
                m_ResetEvent.WaitOne();                
                switch (_state)
                {
                    case ServiceState.Start:
                        {                            
                            Thread t = new Thread(fun_Thread2);
                            t.Start();
                            t.Name = "Thread2";
                            break;
                        }
                    case ServiceState.Stop:
                        {
                            m_ResetEvent_Thread.Set();
                            flag = true;
                            break;
                        }
                }
                // When the child Thread terminates, Then only this thread should terminate
                if (flag == true)
                {
                    // Waiting for notification from child Thread
                    notifyParent.WaitOne();
                    Thread.Sleep(100);
                    break;
                }                
                m_ResetEvent.Reset();                              
            }            
        }
    
        private static ManualResetEvent notifyParent = new ManualResetEvent(false);
    
        private void fun_Thread2()
        {
            while (true)
            {
                if (m_ResetEvent_Thread.WaitOne(1, false))
                {
                    notifyParent.Set();
                    break;
                }
                x++;                
            }
        }     
    }