第26章 计算限制的异步操作(3)

本文详细介绍了如何在.NET Framework中利用CancellationToken实现计算限制操作的协作式取消功能,包括创建CancellationTokenStore对象、获取CancellationToken实例、在循环中检查取消请求以及通过注册回调方法来响应取消操作。此外,还讨论了执行不可取消操作的方法,以及如何通过链接多个CancellationTokenSource来创建一个共享取消源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

26.4 协作式取消

Microsoft .NET Framework提供了一个标准的取消操作模式。这个模式是协作式的,意味着你想取消的操作必须显式地支持取消。对于长时间运行的计算限制操作来说,支持取消是一件很“棒”的事情。所以,你应该考虑为自己的计算限制操作添加取消能力。

System.Threading.CancellationTokenStore对象包含了和管理取消有关的所有状态。构造好一个CancellationTokenStore(一个引用类型)之后,可从它的Token属性获得一个或多个CancellationToken(一个值类型)实例,并传给你的操作,使那些操作可以取消。

在一个计算限制操作的循环中,可以定时调用CancellationToken的IsCancellationRequested属性,了解循环是否应该提前终止,进而终止计算限制的操作。

using System;
using System.Threading;

namespace ThreadStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            ThreadPool.QueueUserWorkItem(o => Print(10, cts.Token));
            Console.WriteLine("Main thread:Go on execute main thread...");
            Thread.Sleep(5000);
            //Cancell the running thread1, then exit app.
            cts.Cancel();
            Thread.Sleep(2000);
            Console.WriteLine("Main thread:Execute completely...");
        }

        static void Print(int seconds,CancellationToken ts)
        {
            for (int i = 0; i < seconds; ++i)
            {
                Console.WriteLine("Thread1:Here is thread1...");
                if (ts.IsCancellationRequested)
                {
                    Console.WriteLine("Thread1:Thread1 was cancelled...");
                    break;
                }
                else
                {
                    Console.WriteLine("Thread1:{0} seconds' tasks in thread1 have been completed...",i);
                    Thread.Sleep(1000);
                }
            }
        }
    }
}
Main thread:Go on execute main thread...
Thread1:Here is thread1...
Thread1:0 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:1 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:2 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:3 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:4 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:Thread1 was cancelled...
Main thread:Execute completely...
Press any key to continue . . .

如果要执行一个操作,并禁止它被取消,可以向该操作传递通过调用CancellationToken的静态None属性而返回的CancellationToken。这个属性返回一个特殊的CancellToken实例,它不和任何CancellationTokenStore对象关联。

如果使用某个特殊CancellationToken实例查询CancellationToken的CanBeCanceled属性,属性会返回false。相反,对于通过查询CancellationTokenSource对象的Token属性而获得的其他所有CancellationToken实例,其属性(CanBeCanceled)都会返回true。

如果愿意,可以登记一个或多个方法在取消一个CancellationTokenSource时调用。然而,每个回调方法都是用CancellationToken的Register方法来登记的。CancellationToken的register方法返回一个CancellationTokenRegistration。

using System;
using System.Threading;

namespace ThreadStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            ThreadPool.QueueUserWorkItem(o => Print(10, cts.Token));
            Console.WriteLine("Main thread:Go on execute main thread...");
            Thread.Sleep(2000);
            //Cancell the running thread1, then exit app.
            cts.Token.Register(() => Console.WriteLine("Canceled 1"));
            cts.Token.Register(() => Console.WriteLine("Canceled 2"));
            cts.Cancel();
            Thread.Sleep(2000);
            Console.WriteLine("Main thread:Execute completely...");
        }

        static void Print(int seconds,CancellationToken ts)
        {
            for (int i = 0; i < seconds; ++i)
            {
                Console.WriteLine("Thread1:Here is thread1...");
                if (ts.IsCancellationRequested)
                {
                    Console.WriteLine("Thread1:Thread1 was cancelled...");
                    break;
                }
                else
                {
                    Console.WriteLine("Thread1:{0} seconds' tasks in thread1 have been completed...",i);
                    Thread.Sleep(1000);
                }
            }
        }
    }
}
输出:

Main thread:Go on execute main thread...
Thread1:Here is thread1...
Thread1:0 seconds' tasks in thread1 have been completed...
Thread1:Here is thread1...
Thread1:1 seconds' tasks in thread1 have been completed...
Canceled 2
Canceled 1
Thread1:Here is thread1...
Thread1:Thread1 was cancelled...
Main thread:Execute completely...
Press any key to continue . . .
可调用Dispose从关联的CancellationTokenSource中删除一个已登记的回调。

可通过链接一组CancellationTokenSource来创建一个CancellationTokenSource对象。任何一个链接的CancellationTokenSource被取消,这个新的CancellationTokenSource对象就会被取消。

using System;
using System.Threading;

namespace ThreadStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cts1 = new CancellationTokenSource();
            CancellationTokenSource cts2 = new CancellationTokenSource();
            CancellationTokenSource cts3 = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
            cts1.Token.Register(() => Console.WriteLine("cts1 canceled..."));
            cts2.Token.Register(() => Console.WriteLine("cts2 canceled..."));
            cts3.Token.Register(() => Console.WriteLine("cts3 canceled..."));
            ThreadPool.QueueUserWorkItem(o => Print(10, cts1.Token));
            ThreadPool.QueueUserWorkItem(o => Print(10, cts2.Token));
            Console.WriteLine("Main thread:Go on execute main thread...");
            Thread.Sleep(2000);
            cts1.Cancel();
            Thread.Sleep(2000);
            Console.WriteLine("Main thread:Execute completely...");
        }

        static void Print(int seconds,CancellationToken ts)
        {
            for (int i = 0; i < seconds; ++i)
            {
                if (ts.IsCancellationRequested)
                {
                    Console.WriteLine("Thread pool thread:Thread was cancelled...");
                    break;
                }
                else
                {
                    Console.WriteLine("Thread pool thread:{0} seconds' tasks have been completed...", i);
                    Thread.Sleep(1000);
                }
            }
        }
    }
}
输出:

Main thread:Go on execute main thread...
Thread pool thread:0 seconds' tasks have been completed...
Thread pool thread:0 seconds' tasks have been completed...
Thread pool thread:1 seconds' tasks have been completed...
Thread pool thread:1 seconds' tasks have been completed...
Thread pool thread:2 seconds' tasks have been completed...
Thread pool thread:Thread was cancelled...
cts1 canceled...
cts3 canceled...
Thread pool thread:3 seconds' tasks have been completed...
Main thread:Execute completely...
Press any key to continue . . .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值