【C# & 多线程】如何停止正在运行中的子线程

通过协作式取消模式

在线程函数中,你可以周期性地检查一个标志位,以确定是否应该停止线程。该标记位可以是共享变量,也可以是CancellationToken。

CancellationTokenSource 和 CancellationToken 被用来发送取消请求,而任务或线程通过检查 CancellationToken.IsCancellationRequested 属性或调用 ThrowIfCancellationRequested 方法来响应这个请求。

using System;  
using System.Threading;  
using System.Threading.Tasks; 

//
// 方式1:使用CancellationToken,停止标志位来停止线程
//
class CancellationTokenExample  
{  
    private CancellationTokenSource _cts = new CancellationTokenSource();  
  
    public void StartWork()  
    {  
        Task.Run(() =>  
        {  
            try  
            {  
                // 模拟长时间运行的工作,直到有取消请求时,退出while  
                while(!_cts.IsCancellationRequested) 
                {  
                    Thread.Sleep(1000); 
                    //如果有取消请求,也可以通过抛出异常结束线程
                    _cts.Token.ThrowIfCancellationRequested();
                }  
            }  
            catch (OperationCanceledException)  
            {  
                //线程被取消  
            }  
        }, _cts.Token);  
    }  
  	// 调用此函数来停止线程
    public void StopWork()  
    {  
        _cts.Cancel();  
    }  
}

//
// 方式2:使用共享变量,停止标志位来停止线程
//
class ThreadStopExample  
{  
    // 停止标志  
    public volatile bool StopRequested { get; set; }  
  
    public void StartWork()  
    {  
        Task.Run(() =>  
        {  
            while (!StopRequested)  
            {   
                Thread.Sleep(1000); // 模拟工作  
            }  
        });  
    }  
  	// 调用此函数来停止线程
    public void StopWork()  
    {  
        StopRequested = true;  
    }  
}

强制终止线程(可能存在资源不能及时释放的泄漏风险)

如果在线程中使用了一个内层的无限循环(while (true)),这将导致线程永远不会退出这个内层循环,此时要退出线程,除非执行强制停止。

using System;  
using System.Threading;  
using System.Threading.Tasks; 


class ForceExitCaseExample
{
    private CancellationTokenSource _cts;
    private Task task;

    public void StartWork()
    {
        //确保线程没有重复运行
        if (task == null || (task.IsCompleted || task.IsCanceled))
        {
            _cts = new CancellationTokenSource();

            task = Task.Run(() =>
            {
            	//注册cancel时,执行Abort方法(不太行,偶尔报异常)
                //_cts.Token.Register(Thread.CurrentThread.Abort);
                
                //注册cancel时,执行Interrupt方法
                _cts.Token.Register(Thread.CurrentThread.Interrupt);
                try
                {
                    bool workDone = false;
                    //模拟长时间运行的工作
                    Thread.Sleep(1000);
                    Console.WriteLine("第一阶段工作完成...");

                    //模拟条件长时间不满足,运行工作死循环
                    while (!workDone)
                    {
                        Console.WriteLine("第二阶段工作中...");
                        Thread.Sleep(999);
                        if (false)
                        {
                            workDone = true;
                        }
                    }
                }
                catch (Exception ex)
                {
                    //线程被取消  
                    Console.WriteLine($"线程异常结束:{ex.Message}");
                }
            }, _cts.Token);

        }
    }
    // 调用此函数来停止线程
    public void StopWork()
    {
        _cts.Cancel();
    }
}
  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值