C# 使用CancellationTokenSource取消多线程

下面我将详细讲解“C#使用CancellationTokenSource取消多线程”的完整攻略。

什么是 CancellationTokenSource

CancellationTokenSource是用来控制CancellationToken的一个类型,CancellationToken是一种用于取消例如Task、ThreadPoolWaitHandle和PLINQ等等API的执行的机制。 CancellationTokenSource的主要作用是创建用于请求取消操作的 CancellationToken。

CancellationTokenSource的使用方法

创建 CancellationTokenSource

首先我们需要创建一个CancellationTokenSource才能开始操作。可以使用无参数构造函数创建默认情况下不存在任何请求取消操作的 CancellationTokenSource,也可以使用一个int类型的参数构造函数创建可以在指定的毫秒数内自动取消的 CancellationTokenSource。

CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

发出取消请求

我们可以使用CancellationTokenSource对象的Cancel方法取消与之关联的所有 CancellationToken。 当取消请求发出后,与 CancellationToken 关联的任务应该立即停止执行,这样可以快速地屏蔽后续进一步的资源密集型操作。我们可以在需要的地方直接调用Cancel方法来发起取消请求。

cancellationTokenSource.Cancel();

是否收到取消请求

通过CancellationToken.IsCancellationRequested属性可以检测与 CancellationToken 关联的请求是否收到取消请求。 以下代码演示了如何执行具有取消选项的异步操作:

public async Task DoAsyncWork(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        // TODO: 执行异步操作
    }

    // 如果收到取消请求,立即抛出OperationCanceledException。
    token.ThrowIfCancellationRequested();
}

与Task关联

现在我们需要让某个Task与CancellationToken关联,以便在取消请求发出后能够响应它们。可以使用Task的Cancellation属性来指定CancellationToken。

Task.Run(() =>
{
    // TODO: 执行需要取消请求的任务
}, cancellationTokenSource.Token);

取消等待的操作

ThreadPool.WaitHandle 也支持 CancellationToken。 取消等待的操作可以通过静态WaitHandle.WaitAny(WaitHandle[], CancellationToken) 或 ThreadPool.RegisterWaitForSingleObject(WaitHandle, delegate, object, int, bool)进行。

示例1

下面是一个简单的示例。程序首先创建了一个CancellationTokenSource,然后启动一个任务,该任务将在指定的时间内循环运行,同时检查CancellationToken,在任务运行的过程中如果取消请求收到则退出循环。

static async Task CancellationTokenExample1(CancellationTokenSource cancellationTokenSource)
{
    Console.WriteLine("开始任务");
    try
    {
        // 执行异步操作,如果在指定时间内完成,就等待响应
        await Task.Delay(3000, cancellationTokenSource.Token);
        Console.WriteLine("任务15秒之后完成了!");
    }
    catch (TaskCanceledException)
    {
        Console.WriteLine("任务收到取消请求!");
    }

    Console.WriteLine("任务结束!");
}

示例2

下面是另一个更复杂的示例,演示如何使用CancellationTokenSource来取消线程池中的操作。

首先定义了一个StartTime,然后在循环中定义了每个线程池中处理的任务,并在执行任务时检查CancellationToken是否已经收到取消请求。

static void CancellationTokenExample2(CancellationTokenSource cancellationTokenSource)
{
    var startTime = DateTime.UtcNow;
    var handles = new[] { new AutoResetEvent(false) };

    Console.WriteLine($"开始任务 {startTime:O}");

    var token = cancellationTokenSource.Token;

    ThreadPool.QueueUserWorkItem(_ => {
        try
        {
            var waitTime = 1000;
            Console.WriteLine($"开启线程1,等待{waitTime}秒");

            while (!token.IsCancellationRequested)
            {
                if (DateTime.UtcNow.Subtract(startTime).Seconds > 15)
                {
                    cancellationTokenSource.Cancel();
                }

                Task.Delay(waitTime, token).Wait(token); // 等待操作
                Console.WriteLine($"线程1等待了{waitTime}秒后完成了它的工作。");
                handles[0].Set();
            }

            Console.WriteLine("取消操作完成。");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("线程1收到取消请求。");
        }
    }, null);

    ThreadPool.RegisterWaitForSingleObject(handles[0], _ => {
        try
        {
            var waitTime = 500;
            Console.WriteLine("开启线程2,等待500毫秒");
            Task.Delay(waitTime).Wait(token);
            Console.WriteLine("线程2等待500毫秒后完成了它的工作。");
            handles[0].Set();
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("线程2收到取消请求。");
        }
    }, null, TimeSpan.FromSeconds(1), false);

    WaitHandle.WaitAll(handles);
    Console.WriteLine("任务结束!");
}

这样就完成了使用CancellationTokenSource来取消多线程的攻略了,希望本文能够帮助到你。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 使用CancellationTokenSource取消多线程 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • .Net Core简单使用Mvc内置的Ioc(续)

    .NET Core简单使用Mvc内置的Ioc(续) 在上一篇攻略中,我们介绍了如何在.NET Core应用程序中使用Mvc内置的Ioc容器。在本攻略中,我们将继续介绍如何使用Mvc内置的Ioc容器,并提供两个示例说明。 1. 注册服务 在.NET Core应用程序中,可以使用IServiceCollection接口的AddTransient、AddScope…

    C# 2023年5月16日
    00
  • ItemsControl 数据绑定的两种方式

    我来为你讲解“ItemsControl 数据绑定的两种方式”的完整攻略。 一、介绍 在 WPF 中,我们通常使用 ItemsControl 来呈现一组数据集合。ItemsControl 提供了两种数据绑定的方式:通过 ItemsSource 属性绑定数据集合,或者通过数据模板绑定单个对象。 二、数据绑定方式一:ItemsSource 属性绑定数据集合 在此数…

    C# 2023年6月6日
    00
  • C#递归实现显示文件夹及所有文件并计算其大小的方法

    下面是“C#递归实现显示文件夹及所有文件并计算其大小的方法”的完整攻略。 1. 确定递归终止条件 首先,我们要确定递归的终止条件。在本题中,终止条件一般是当遍历到文件时,直接输出文件的名称和大小,并返回上一级目录继续遍历。因此,我们可以使用File和Directory类来判定当前路径是否为文件或目录,并在遇到文件时直接输出。 2. 确定遍历方式 其次,我们需…

    C# 2023年6月1日
    00
  • abp(net core)+easyui+efcore实现仓储管理系统——模块管理升级之上(六十一)

     Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二) abp(net core)+easyui+efcore实现仓储管理系统——领域层创建实体(三…

    C# 2023年4月17日
    00
  • C#验证给定字符串是否为数字的方法

    下面是详细的C#验证给定字符串是否为数字的方法攻略: 方法一:使用int.TryParse方法 int.TryParse方法可以将字符串转换为整型变量,如果转换成功则返回true,否则返回false。因此,我们可以利用这个方法来检查输入的字符串是否是数字。 下面是示例代码: string inputString = "12345"; in…

    C# 2023年6月8日
    00
  • 详解如何在ASP.NET Core中编写高效的控制器

    如何在ASP.NET Core中编写高效的控制器 在ASP.NET Core应用程序中,控制器是处理HTTP请求的核心组件。编写高效的控制器可以提高应用程序的性能和响应速度。本攻略将介绍如何在ASP.NET Core中编写高效的控制器。 步骤 以下是在ASP.NET Core中编写高效的控制器的步骤: 使用依赖注入。 在ASP.NET Core应用程序中,我…

    C# 2023年5月17日
    00
  • 使用VS2022在ASP.NET Core中构建轻量级服务

    下面是使用VS2022在ASP.NET Core中构建轻量级服务的完整攻略: 简介 ASP.NET Core是一个跨平台的开源框架,它提供了构建 Web 应用程序和服务的工具和框架。本攻略将带你使用VS2022在ASP.NET Core中构建轻量级服务。 步骤一:创建 ASP.NET Core 项目 打开 Visual Studio 2022,选择“创建新项…

    C# 2023年6月3日
    00
  • 在SQL Server中使用CLR调用.NET方法实现思路

    在SQL Server中使用CLR调用.NET方法可以扩展数据库的功能,下面是实现思路的完整攻略: 1.启用CLR 要在SQL Server中使用CLR,首先需要在服务器级别启用CLR。可以通过以下步骤启用CLR: 在SQL Server Management Studio中打开一个新的查询窗口。 运行以下T-SQL代码: sp_configure ‘clr…

    C# 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部