C#终止线程的方法

微软的文档中不建议以Abort的方式终止线程。比如终止线程的瞬间,FileStream没有释放,会出现问题,等等。

Framework4.0提供了标准取消模式:协作式取消(Cooperative Cancellation),工作线程会定期检查终止线程的标识。取消的时候,协作类中设置这个标识,然后等待工作线程响应。BackgroundWorker类中有类似的标识,可进行对比。

Demo 1:BackgroundWorker类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;
using System.ComponentModel;

namespace BackgroundWorkerDemo
{
    class Program
    {
        static BackgroundWorker bw; //namespace是 ComponentModel

        static void Main(string[] args)
        {
            bw = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };

            bw.DoWork += bw_DoWork; //将方法挂载到DoWork
            bw.RunWorkerCompleted += bw_RunWorkerCompleted; 


            bw.RunWorkerAsync();

            Console.ReadLine();
            if (bw.IsBusy) 
                bw.CancelAsync();

        }

        static void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            
            Console.WriteLine(e.Argument);

            Console.ResetColor();
            int i = 0;
            while(true)
            {
                if (bw.CancellationPending)
                {
                    e.Cancel = true; 
                    return;
                }
                
                bw.ReportProgress(i);
                i++;
                Thread.Sleep(100); 
                Console.WriteLine("DoWork progress: " + i.ToString());

                if (i == 5) //可以在工作线程中退出
                {
                    e.Cancel = true;
                    return;
                }
            }
        }

        static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                Console.WriteLine("you canceled,the progress quits");
                
            }
            else if (e.Error != null)
            {
                Console.WriteLine("Worker exception:" + e.Error.ToString());
            }
            else
            {
                Console.WriteLine("Complete :" + e.Result);
            }
        }
    }
}

Demo 2 :开启启两个线程,分别向对应文本框中添加信息

        private void button4_Click(object sender, EventArgs e)// 线程的终止,不建议使用Abort
        {
            //第一种方法:Abort 终止线程
            //if (AddThread.IsAlive && AddThread != null)
            //{
            //    AddThread.Abort();
            //}
            //if (AddThread2nd.IsAlive && AddThread2nd != null)
            //{
            //    AddThread2nd.Abort();
            //}


            //第二种方法
            canceler.Cancel();
            canceler2nd.Cancel();
            canceler.Token.Register(() =>
            {
                MessageBox.Show("工作线程被终止");
            });

            Thread1st = null;
            AddThread2nd = null;
        }
有一个问题,快速点击start和stop,线程停止没有问题,但是有时候却只开启了一个线程。可能是因为IsCancellationRequested的值没有及时更新为false。
参考https://blog.gkarch.com/threading/part3.html中第4部分的内容,写个线程终止类,代码如下:

class RulyCanceler
{
    readonly object _locker = new object();
    bool cancelRequest = false;
    bool IsCancellationRequest
    {
        get
        {
            lock (_locker)
            {
                return cancelRequest;
            }
        }
    }

    public void Cancel()
    {
        lock (_locker)
        {
            cancelRequest = true;
        }
    }

    public void Resume()
    {
        cancelRequest = false;
    }

    public void ThrowIfCancellationRequested()
    {
        if (IsCancellationRequest)
        {
            throw new OperationCanceledException();
        }
    }
}
            try
            {
                while (true)
                {
                    canceler.ThrowIfCancellationRequested();


                    Thread.Sleep(10);
                    AddHandleNew(i);
                    i++;


                }
            }
            catch (OperationCanceledException)
            {
                canceler.Resume();
                return;
            }
Resume需要放在catch(OperationCanceledException)中,也就是说catch到取消事件后,要将类中的取消标记置为false。这样才能避免反复点击start和stop出问题。



### 在 C# 中正确终止线程方法C# 中,终止线程可以通过多种方式实现,包括 `Thread.Abort` 和 `Thread.Join` 等方法。以下是关于这些方法的详细说明和示例代码。 #### 使用 `Thread.Abort` 方法终止线程 `Thread.Abort` 方法会引发线程上的 `ThreadAbortException` 异常,从而开始终止线程的过程[^3]。需要注意的是,调用此方法并不一定立即终止线程线程可能仍然需要一些时间来处理异常并退出[^1]。 以下是一个使用 `Thread.Abort` 的示例: ```csharp using System; using System.Threading; class Program { static void Main() { Thread newThread = new Thread(new ThreadStart(TestMethod)); newThread.Start(); Thread.Sleep(1000); // 让主线程等待一段时间以确保子线程启动 Console.WriteLine("Main aborting new thread."); newThread.Abort("Information from Main."); // 触发线程终止 newThread.Join(); // 等待线程完全终止 Console.WriteLine("New thread terminated - Main exiting."); } static void TestMethod() { try { while (true) { Console.WriteLine("New thread running."); Thread.Sleep(1000); } } catch (ThreadAbortException abortException) { Console.WriteLine((string)abortException.ExceptionState); // 捕获终止信息 } } } ``` #### 使用 `Thread.Join` 方法等待线程完成 `Thread.Join` 方法会让当前线程(通常是主线程)阻塞,直到指定的线程完成执行[^4]。这可以用来确保在继续执行其他操作之前,某个线程已经安全地结束。 以下是一个使用 `Thread.Join` 的示例: ```csharp using System; using System.Threading; class Program { static void Main() { Thread th = new Thread(new ThreadStart(ThreadWork)); th.Start(); Thread.Sleep(1000); // 主线程等待一段时间 try { th.Abort(); // 尝试终止线程 Console.WriteLine("线程的状态: " + th.ThreadState.ToString()); th.Join(); // 等待线程完全终止 } catch (Exception e) { Console.WriteLine(e.Message.ToString()); } Console.WriteLine("线程的状态: " + th.ThreadState.ToString()); Console.ReadLine(); } static void ThreadWork() { for (int i = 0; i < 1000000; i++) { Console.WriteLine("执行了{0}次", i); } } } ``` #### 更安全的线程终止方法 直接使用 `Thread.Abort` 可能会导致资源泄漏或数据不一致的问题,因为它强制终止线程而不考虑线程的当前状态。因此,推荐通过设置标志位的方式优雅地终止线程。 以下是一个更安全的终止线程的示例: ```csharp using System; using System.Threading; class Program { private static bool _shouldStop = false; static void Main() { Thread workerThread = new Thread(WorkerMethod); workerThread.Start(); Thread.Sleep(5000); // 主线程等待一段时间 _shouldStop = true; // 设置标志位以通知线程停止 workerThread.Join(); // 等待线程安全退出 Console.WriteLine("线程已安全终止!"); } static void WorkerMethod() { while (!_shouldStop) { Console.WriteLine("线程正在运行..."); Thread.Sleep(1000); } Console.WriteLine("线程收到停止信号,准备退出..."); } } ``` #### 注意事项 - 使用 `Thread.Abort` 可能会导致未捕获的异常或资源泄漏,因此应尽量避免使用。 - 推荐通过设置标志位的方式让线程自行退出,这种方式更加安全且可控[^3]。 - 在多线程环境中,必须确保对共享资源的访问是线程安全的,可以通过锁机制(如 `lock` 关键字)来实现。 ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值