C#多线程编程实战(从入门到精通系列)第三篇 正确终止线程

正确终止线程的方法

在介绍正确方法前,我们先看下传统的停止方法:

thread.stop();
stop方法用来强行终止正在运行或挂起的线程。
这个方法的危险之处在于:

如果线程当前正在执行的是一段非托管代码(为CLR而编写以及使用CLR服务的代码叫"托管代码",而那些未使用CLR服务的代码(也就是你多年以来一直编写的代码)叫"非托管代码"。),那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发ThreadAbortException。当然,即便是在CLR环境中,ThreadAbortException也不会立即引发。


正确方法:

1.使用退出标志终止线程

示例一

public static bool exit = false;  
static void Main(string[] args)
{
    Thread t = new Thread(PrintNumbers);
	t.Start();
    Thread.Sleep(6000);
    exit = true;
}

static void PrintNumbers()
{
    Console.WriteLine("Starting...");
    for (int i = 1; i < 100; i++)
    {
        if (exit) break;
        Thread.Sleep(TimeSpan.FromSeconds(2));
        Console.WriteLine(i);
    }
}</span>

示例二

public static bool exit = false;  
static void Main(string[] args)
{
    Thread t = new Thread(Run);
	t.Start();
    Thread.Sleep(6000);
    exit = true;
}

static void Run()
{
    while (!exit)
    {
        Thread.Sleep(TimeSpan.FromSeconds(2));
        Console.WriteLine("Running...");
    }
}

当PrintNumbers或Run方法执行完后,线程就会退出。但有时PrintNumbers方法是要很久而Run方法永远不会结束的。如果我们用for循环去处理一些大量数据,或用while在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如for,while循环。但要想使for,while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制for,while循环是否退出。

2.使用Interrupt方法终止线程

使用Interrupt方法来终端线程将抛出一个ThreadInterruptedException异常。

示例一

static void Main(string[] args)
{
    Thread t = new Thread(RunInterrupt);
    t.Start();
    Thread.Sleep(6000);
    t.Interrupt();
}

static void RunInterrupt()
{
    try
    {
        while (true)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine("Running...");
        }</span><span style="font-size:18px;">
    }
    catch (Exception)
    {
        Console.WriteLine("Stoped");
    }
}

 
3.标准的取消模式:协作式取消(Cooperative Cancellation) 

static CancellationTokenSource cts = new CancellationTokenSource();
static void Main(string[] args)
{
    Console.WriteLine("按任意键终止线程!");
    Thread t = new Thread(() =>
    {
        while (true)
        {
            if (cts.Token.IsCancellationRequested)
            {
                Console.WriteLine("线程被终止!");
                break;
            }
            Console.WriteLine(DateTime.Now.ToString());
            Thread.Sleep(1000);
        }
    });
    t.Start();
            
    Console.ReadKey();
    cts.Cancel();
}

调用者使用 CancellationTokenSource的Cancle方法通知工作线程退出。工作线程则以大致1000毫秒的频率一边工作,一边检查是否有外界传入进来的Cancel信号。若有这样的信号,则负责退出。可以看到,在正确停止线程的机制中,真正起到主要作用的是线程本身。

协作式取消中的关键类型是CancellationTokenSource。它有一个关键属性 Token,Token是一个名为CancellationToken的值类型。CancellationToken继而进一步提供了布尔值的属性 IsCancellationRequested作为需要取消工作的标识。CancellationToken还有一个方法尤其值得注意,那就是 Register方法。它负责传递一个Action委托,在线程停止的时候被回调,使用方法如:

cts.Token.Register(() =>
{
    Console.WriteLine("线程被终止了。");
});

以上就是正确终止线程的三种方法了,推荐使用第三种,最为标准。




  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值