tnblog
首页

C# 使用CancellationTokenSource取消多线程

424人阅读 2018/11/26 14:00 评论:0 收藏
分类: .NET


             

有时间我们在使用多线程的时候,需要取消线程的执行,可以使用CancellationTokenSource来取消对Task开辟多线程的取消

 

如下:我们点击一个按钮开启线程,然后点击取消按钮取消该线程的执行

CancellationTokenSource cts ;
        /// <summary>
        /// 开启线程
        /// </summary>
        private void button1_Click(object sender, EventArgs e)
        {
            //重新实例化cts.Token就会不一样,不然再次点击的时候会报错,提示线程已经执行完毕
            cts = new CancellationTokenSource();
 
            Task task = new Task(() =>
            {
                Thread.Sleep(1500);
 
                try
                {
                    cts.Token.ThrowIfCancellationRequested();
                    MessageBox.Show("线程被执行");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("线程被取消");
                }
 
            }, cts.Token);
            task.Start();
 
            //如果放到这里有可能线程还没有开始执行就被取消了
            //cts.Cancel(true);
        }
 
        /// <summary>
        /// 取消线程
        /// </summary>
        private void button2_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }


几点关键问题解释:


 1:为什么线程里边去调用 Thread.Sleep(1500);

          因为如果不让线程暂停一下,你在点击开启线程后。还没有来得及点击取消线程,线程都已经执行完毕了这个时候

          再去取消线程是没有什么意义的。


2: cts.Cancel()

          这句话其实只是设置一个状态,设置该对象一个熟悉为true而已,也就是设置cts.IsCancellationRequested为ture。

          所以他根本没有真正的去取消线程的执行,只是设置一个状态而已。


3:cts.Token.ThrowIfCancellationRequested();

          因为上面说的cts.Cancel()只是设置一个状态而已,线程不会真正被取消。其实线程开启后,现在都是要执行完的,

         我们并不能真正去取消线程的执行,只是从逻辑上去取消线程需要处理的逻辑。

         这句话的意思其实就是检查cts.Cancel()设置的属性状态,也就是cts.IsCancellationRequested是否为true,如果为

         true就抛出一个异常,从而终止线程的执行

         也就是说其实这句话完全可以我们自己来实现



同时取消多个线程:

同时取消多个线程,其实也很简单,我们不需要有多少个线程就去实例化多少个CancellationTokenSource,

多个线程绑定顶一个CancellationTokenSource的token然后调用该对象的cancel就可以同时取消多个线程了。

CancellationTokenSource cts;
        /// <summary>
        /// 开启线程
        /// </summary>
        private void button1_Click(object sender, EventArgs e)
        {
            //重新实例化cts.Token就会不一样,不然再次点击的时候会报错,提示线程已经执行完毕
            cts = new CancellationTokenSource();
 
            for (int i = 0; i < 5; i++)
            {
                Task task = new Task((obj) =>
                {
                    Thread.Sleep(1500);
 
                    try
                    {
                        //cts.Token.ThrowIfCancellationRequested();
                        //检查状态,检查线程是否已经被取消,如果取消则自己跑出来一个线程
                        if (cts.Token.IsCancellationRequested)
                            throw new OperationCanceledException();
                        MessageBox.Show("线程" + obj + "被执行");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("线程" + obj + "被取消");
                    }
 
                }, i, cts.Token);
                task.Start();
            }
            //如果放到这里有可能线程还没有开始执行就被取消了
            //cts.Cancel(true);
        }
 
        /// <summary>
        /// 取消线程
        /// </summary>
        private void button2_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }





请先登录

{{item.title}}

{{item.content}}
不能简单的解决问题,那是设计与做法有问题
博主搜索
文章类别
CSS 5篇
云服务 2篇
Git 4篇
.NET 29篇
Android 0篇
软件架构 4篇
.NET Core 15篇
.NET MVC 3篇
英语 3篇
随笔 3篇
Bootstrap 1篇
Redis 12篇
编辑器 2篇
Js相关 6篇
Layui 2篇
Oracle 7篇
Python 2篇
数据库 2篇
EF 2篇
微信 2篇
前端 1篇
消息队列 1篇
最新文章
为什么要使用webapi而不直接使用controller
net core发布到IIS常见错误
net core依赖注入
NET CORE配置EF连接字符串
Net Core使用依赖注入来装载EF的上下文对象
下载net core
Sqlerver添加用户与授权
net core中使用url编码与解码操作
net core启动报错Unable to configure HTTPS endpoint. No server certificate was specified
.net core使用response
ef6动态添加条件
最新评价
{{item.ArticleTitle}}
{{item.BlogName}} : {{item.Content}}