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日

相关文章

  • C#中DataSet转化为实体集合类的方法

    将C#中的DataSet转化为实体集合类的方法涉及到数据集合类和实体类之间的转换。下面是实现这个过程的攻略: 步骤一:创建实体类 首先,我们需要创建实体类。这个类必须符合我们数据库中表的结构。一个简单的实体类示例如下: public class User { public int Id { get; set; } public string Name { g…

    C# 2023年6月3日
    00
  • c#开发的程序安装时动态指定windows服务名称

    接下来我将详细讲解如何在C#开发的程序安装时动态指定Windows服务名称的完整攻略。具体来说,我们要在程序安装时动态指定Windows服务名称的关键在于(1)编写安装程序时获取服务名称,(2)在安装过程中指定服务名称。 获取服务名称 在编写安装程序时获取当前安装程序所安装的服务的名称是至关重要的,可以通过下面的方法实现: string serviceNam…

    C# 2023年6月1日
    00
  • C# File.ReadAllBytes(string path):读取指定文件的所有字节内容

    File.ReadAllBytes(string path)是C#中一个用于读取指定文件的字节流并将其以字节数组的形式返回的方法。 作用: 该方法用于将指定文件中的所有字节读入一个字节数组中,并返回该字节数组。可以使用此方法来读取任何类型的文件,包括图像、声音和文本文件等。 使用方法攻略: 要使用File.ReadAllBytes方法,需要在代码中使用以下命…

    C# 2023年4月19日
    00
  • 一篇文章带你轻松了解C# Lock关键字

    一篇文章带你轻松了解C# Lock关键字 Lock关键字是什么 Lock是C#编程中非常重要的一个关键字,主要用来进行多线程编程时的同步控制。在多线程程序中,不同的线程会同时对同一数据进行访问,如果没有同步控制,则有可能发生数据竞争的问题。使用Lock关键字可以保证在同一时间只有一个线程对共享资源进行访问。 Lock关键字的用法 Lock关键字用法非常简单,…

    C# 2023年5月15日
    00
  • 详解C#多线程编程之进程与线程

    详解C#多线程编程之进程与线程 引言 C#是一门面向对象的编程语言,当需要实现客户端或服务端的高并发处理时,多线程就是一种非常有效的解决方案了。而多线程的核心是进程和线程。本文主要讲解C#多线程编程之进程与线程。 进程和线程的理解 进程 进程是一个正在执行的程序实例。它在计算机中占用一定的资源,包括内存、CPU以及网络资源等等。进程是操作系统对资源分配的基本…

    C# 2023年5月15日
    00
  • asp.net 用户控件读取以及赋值

    让我们来详细讲解一下如何读取和赋值 ASP.NET 用户控件。 什么是 ASP.NET 用户控件? ASP.NET 用户控件是由 ASP.NET 页面和服务器控件组成的。它们是可重用的模块,可以在多个页面中使用,并且可以像其他服务器控件一样自定义和配置。用户控件通常用于在多个页面中使用相同的用户界面元素。 如何创建 ASP.NET 用户控件? 要创建 ASP…

    C# 2023年6月3日
    00
  • C#单线程和多线程的端口扫描器应用比较详解

    C#单线程和多线程的端口扫描器应用比较详解 一、介绍 本文主要介绍C#单线程和多线程的端口扫描器应用比较,主要包括以下内容: 单线程端口扫描器原理及实现 多线程端口扫描器原理及实现 单线程与多线程端口扫描器的比较分析 二、单线程端口扫描器原理及实现 单线程端口扫描器是指只有一个线程去扫描指定的ip和端口。实现思路如下: 1. 获取目标ip地址和端口范围 2.…

    C# 2023年5月15日
    00
  • C#网络编程中常用特性介绍

    C#网络编程中常用特性介绍 在C#网络编程中,有很多常用特性值得去了解和掌握。下面将会介绍几个常用的特性及其用法。 1. Socket Socket是建立网络连接最基础的类之一。它提供了一组通信协议,并在套接字上实现这些协议。以下是一个简单的Socket示例,用于连接服务器、发送数据和接收数据。 using System; using System.Net;…

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