C#多线程之取消架构介绍

C#多线程之取消架构介绍攻略

什么是C#多线程取消架构

在C#中,我们可以使用多线程来进行异步编程,但是在实际场景中,有时候由于各种原因,我们需要中途取消一个正在运行的线程。而为了达到这个目的,C#中引入了取消架构(Cancellation Framework),通过这个机制,我们可以实现对多线程操作的取消。在该机制中,我们创建一个CancellationTokenSource的实例,然后将它的Token对象传递给所有的任务,并在需要取消这些任务时,调用该Token对象的Cancel方法即可。

如何使用C#多线程取消架构

创建CancellationTokenSource实例

我们先创建一个CancellationTokenSource实例:

CancellationTokenSource cts = new CancellationTokenSource();

异步执行需要取消的任务

我们有一个需要被取消的异步任务,这个任务可能需要运行几秒钟或几分钟,我们可以使用Task.Run方法来启动这个任务,并将CancellationTokenSource的Token对象作为参数传入:

var task = Task.Run(() => {
    // 执行需要被取消的任务
    // 可以使用while循环来模拟一个长时间任务,这里使用Thread.Sleep来模拟
    int i = 0;
    while (true) {
        if (cts.Token.IsCancellationRequested) {
            break;
        }
        Console.WriteLine("Task is running: {0}", ++i);
        Thread.Sleep(1000);
    }
    Console.WriteLine("Task is finished.");
}, cts.Token);

在该任务中,我们使用了while循环,并且在每次循环中都检测CancellationTokenSource的Token对象是否被取消,如果是,则跳出循环,结束任务。这里我们使用Thread.Sleep方法来模拟一个长时间运行的任务。

取消任务

当我们需要取消该异步任务时,可以直接调用CancellationTokenSource的Cancel方法即可:

cts.Cancel();

Cancel方法将会通知所有使用该Token对象的任务,并使这些任务停止运行。

检查任务是否被取消

我们也可以在任务中检查Token是否被取消,如果是,则立即停止任务:

for (int i = 0; i < 10; i++) {
    if (cts.Token.IsCancellationRequested) {
        Console.WriteLine("Task is cancelled.");
        return;
    }
    Console.WriteLine("Task is running: {0}", i);
    Thread.Sleep(1000);
}
Console.WriteLine("Task is finished.");

示例一:向多个URL异步请求数据

下面我们来看一个使用C#多线程取消架构的例子,假设我们需要从多个URL异步请求数据,并将它们合并到一个结果中:

async Task<string> GetDataAsync(string url, CancellationToken ct) {
    using (HttpClient client = new HttpClient()) {
        using (HttpResponseMessage response = await client.GetAsync(url, ct)) {
            var data = await response.Content.ReadAsStringAsync();
            return data;
        }
    }
}

async Task<string> GetDataFromUrlsAsync(string[] urls, CancellationToken ct) {
    List<Task<string>> tasks = new List<Task<string>>();
    foreach (string url in urls) {
        tasks.Add(GetDataAsync(url, ct));
    }

    string[] result = await Task.WhenAll(tasks.ToArray());
    return string.Join(",", result);
}

在该例子中,我们首先定义了一个GetDataAsync方法来异步获取指定URL的数据,该方法使用HttpClient来发起网络请求,并将获取到的数据返回。

然后我们定义了一个GetDataFromUrlsAsync方法来同时从多个URL请求数据,并将它们合并到一个结果中。在该方法中,我们使用List>来保存从每个URL请求数据的任务,然后使用Task.WhenAll方法等待所有任务完成,并将它们返回的数据合并到结果中。

最后我们调用该方法,并在需要取消请求时,调用CancellationTokenSource的Cancel方法:

CancellationTokenSource cts = new CancellationTokenSource();
string[] urls = new string[] { "http://url1.com", "http://url2.com", "http://url3.com" };
Task<string> task = GetDataFromUrlsAsync(urls, cts.Token);
cts.CancelAfter(TimeSpan.FromSeconds(5));
try {
    string result = await task;
    Console.WriteLine(result);
} catch (TaskCanceledException) {
    Console.WriteLine("Task is cancelled.");
}

在该代码中,我们首先创建一个CancellationTokenSource实例,并将它的Token对象传递给GetDataFromUrlsAsync方法。然后我们调用该方法,使用string[]数组来保存需要请求的URL。

在调用方法后,我们使用cts.CancelAfter方法来5秒钟后自动取消请求,在等待方法返回的过程中,如果任务被取消,则会抛出TaskCanceledException异常,我们可以在catch块中处理这个异常。

示例二:使用Parallel.ForEach执行任务

在下面这个例子里,我们使用Parallel.ForEach方法来执行多个任务,而使用CancellationTokenSource来取消所有任务:

var cts = new CancellationTokenSource();
string[] urls = new string[] { "http://url1.com", "http://url2.com", "http://url3.com" };
try {
    Parallel.ForEach(urls, new ParallelOptions { CancellationToken = cts.Token }, url => {
        // 执行任务,这里使用HttpClient来请求数据
        using (var client = new HttpClient()) {
            var response = client.GetAsync(url, cts.Token).Result;
            Console.WriteLine(response.Content.ReadAsStringAsync().Result);
        }
    });
} catch (OperationCanceledException) {
    Console.WriteLine("Tasks are cancelled.");
}

在该例子中,我们使用Parallel.ForEach方法来并行执行多个任务,使用CancellationTokenSource的Token对象来取消所有任务。我们使用using语句来管理HttpClient的生命周期,并在任务中使用HttpClient来请求网络数据。

最后我们使用try-catch块来捕获OperationCanceledException异常,该异常会在任务被取消时抛出。

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

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

相关文章

  • 输出的文本实现对齐的方法(超简单)

    概述: 实现文本输出对齐的方法有很多,其中最简单的方法就是使用Markdown语法中的制表符\t。制表符\t可以在文本中插入一个制表符,从而实现对齐。 步骤: 1、在需要对齐的文本中,使用制表符\t进行对齐。制表符\t的作用就是让文本输出一个制表符的位置,从而实现对齐。 2、在Markdown语法中,需要使用代码块(反引号)将代码块包含起来。代码块中的内容会…

    C# 2023年6月7日
    00
  • 记一次 .NET 某手术室行为信息系统 内存泄露分析

    一:背景 1. 讲故事 昨天有位朋友找到我,说他的程序内存存在泄露导致系统特别卡,大地址也开了,让我帮忙看一下怎么回事?今天上午看了下dump,感觉挺有意思,在我的分析之旅中此类问题也蛮少见,算是完善一下体系吧。 二:WinDbg 分析 1. 到底是哪里的泄露 在.NET高级调试训练营中,我多次告诉学员们,在分析此类问题时一定要搞清楚是托管还是非托管的问题,…

    C# 2023年4月18日
    00
  • C#微信公众号与订阅号接口开发示例代码

    下面我将详细讲解如何进行C#微信公众号与订阅号接口开发,并提供以下两个示例说明: 示例一:获取微信公众号基本信息 步骤一:申请开发者账号 首先,你需要到微信公众平台官网上注册一个开发者账号。 步骤二:创建公众号 在申请开发者账号后,你需要创建一个新的公众号。 步骤三:获取AppID和AppSecret 创建公众号后,在公众号设置页面可以获取到AppID和Ap…

    C# 2023年5月31日
    00
  • C#泛型实例详解

    C#泛型实例详解 本文将详细讲解C#泛型的使用方法与实例,并通过两个示例进行演示。 什么是泛型 泛型在C#中的作用类似于Java中的模板,它能够将具体的数据类型参数化,使得类或者方法可以适应多种不同类型的数据。 使用泛型还有以下优点: 提高程序的可读性和可维护性,减少重复的代码 编译时类型安全,避免因类型错误导致的运行时异常 避免了装箱和拆箱操作,提高了程序…

    C# 2023年5月15日
    00
  • SQL Server中字符串函数的用法详解

    SQL Server中字符串函数的用法详解 在SQL Server中,有许多用于处理字符串的函数,包括字符串拼接、截取、替换等。本文将详细讲解SQL Server中各种字符串函数的用法。 1. CONCAT函数 CONCAT函数用于将多个字符串拼接为一个字符串。它的语法如下: CONCAT ( string1, string2 [, stringN ] ) …

    C# 2023年6月7日
    00
  • winform 实现选择文件和选择文件夹对话框的简单实例

    以下是“winform 实现选择文件和选择文件夹对话框的简单实例”的攻略。 1. 引言 在编写 winform 程序时,我们常常需要用到让用户选择文件或者目录的功能。实现这个功能,我们需要用到 System.Windows.Forms 命名空间中的 OpenFileDialog 和 FolderBrowserDialog 类。 2. 实现选择文件对话框 接下…

    C# 2023年6月1日
    00
  • C# SynchronizationContext以及Send和Post使用解读

    C#中的SynchronizationContext是用于处理多线程并发问题的一种机制,它能够确保在多线程环境下的UI操作不会出现问题,保障了程序的稳定性和可靠性。在使用SynchronizationContext时,我们借助它提供的Send和Post方法来将指定的操作添加到指定的队列中,等待处理。 SynchronizationContext的作用 Syn…

    C# 2023年6月6日
    00
  • Asp.net(C#)实现验证码功能代码

    接下来我将为您详细讲解Asp.net(C#)实现验证码功能代码的完整攻略。 1. 简介 验证码,就是为了防止恶意机器人向网站提交请求或恶意注册而设计的一种验证方法。通过验证码,网站可以判断请求来源的真实性并提高安全性。 2. 实现过程 首先,我们需要生成一个随机的验证码,并将其显示在前台;其次,用户需要输入验证码并进行验证。下面,我将分两部分进行详细讲解。 …

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