C# 的TaskScheduler

        在C#中,TaskScheduler 是一个抽象类,用于控制任务的执行方式,特别是它们如何被安排到线程池中的线程上执行。

TaskScheduler 负责将 Task 对象排队并决定何时、以何种方式执行这些任务。

TaskScheduler 的作用

  • 调度任务:将任务分配给线程池中的线程执行。
  • 控制并发:通过限制同时执行的任务数量来控制并发级别。
  • 异常处理:虽然不是直接由 TaskScheduler 处理异常,但它通过控制任务的执行环境间接影响了异常的处理方式。

如何使用 TaskScheduler

        通常,我们不需要直接创建 TaskScheduler 的实例,因为 Task 类和 TaskFactory 类提供了足够的方法来使用默认的 TaskScheduler(通常是 TaskScheduler.Default,它对应于线程池)。

        然而,在某些情况下,你可能需要自定义 TaskScheduler 来满足特定的需求。

示例:使用默认的 TaskScheduler

        大多数情况下,你不需要显式地使用 TaskScheduler,因为 Task.Run 和 Task.Factory.StartNew(当不提供 TaskScheduler 时)默认使用 TaskScheduler.Default

// 使用 Task.Run 启动一个后台任务  
Task.Run(() =>  
{  
    // 这里执行耗时操作  
    Console.WriteLine("任务正在后台执行...");  
    Thread.Sleep(1000); // 模拟耗时操作  
    Console.WriteLine("任务完成.");  
});  
  
// 等待任务完成(仅为了示例,实际代码中通常不会这样做)  
Task.Delay(2000).Wait(); // 确保主线程等待足够长的时间以看到后台任务的结果
示例:自定义 TaskScheduler

        如果你需要自定义任务调度逻辑(例如,限制并发任务的数量),你可以继承 TaskScheduler 并实现其抽象方法。然而,这通常是一个高级用法,需要深入理解多线程编程和 Task 的工作机制。

        这里是一个简化的例子,说明如何继承 TaskScheduler,但请注意,这个例子并没有真正实现任务调度逻辑,而只是展示了如何开始自定义:

public class LimitedConcurrencyTaskScheduler : TaskScheduler  
{  
    // 假设我们有一个限制并发数的字段  
    private readonly int _maxConcurrencyLevel;  
    private int _activeTasks;  
  
    public LimitedConcurrencyTaskScheduler(int maxConcurrencyLevel)  
    {  
        _maxConcurrencyLevel = maxConcurrencyLevel;  
    }  
  
    // 省略了 QueueTask, TryExecuteTaskInline, GetScheduledTasks 等方法的实现  
  
    // 这里只是展示如何开始,实际上你需要实现这些方法来控制任务的调度  
    protected override void QueueTask(Task task)  
    {  
        // 这里应该有逻辑来将任务添加到队列中,并根据需要执行它们  
        // 但由于这是示例,我们只是简单地将任务计数增加  
        Interlocked.Increment(ref _activeTasks);  
  
        // 注意:这实际上并没有真正地将任务排队或执行,只是演示  
  
        // 在真实实现中,你应该在这里将任务放入某种队列中,并在有可用线程时执行它们  
    }  
  
    // ... 其他方法的实现  
}  
  
// 注意:上面的 LimitedConcurrencyTaskScheduler 只是一个框架,并没有完整实现  
// 在实际使用中,你需要完整实现所有抽象方法,并根据需要添加额外的逻辑

        由于自定义 TaskScheduler 的实现相对复杂,且容易出错,因此通常建议仅在我们确实需要控制任务执行的细节时才这样做。在大多数情况下,使用默认的 TaskScheduler 或 Task.Run 就足够了。


补充:

        在C#中,如果有大量task同时执行,假设我们需要限制同时执行的Task的最大数量为5,我们可以通过自定义一个TaskScheduler来实现,但这种方法相对复杂且容易出错。更常见和简单的方法是使用SemaphoreSlim来限制并发量

   SemaphoreSlim是一个轻量级的信号量,用于控制对共享资源的并发访问。你可以使用它来限制同时执行的Task数量。

        下面是一个使用SemaphoreSlim来限制Task最大执行个数的例子:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading;  
using System.Threading.Tasks;  
  
class Program  
{  
    static SemaphoreSlim semaphore = new SemaphoreSlim(5); // 初始化为5,表示同时允许5个任务执行  
  
    static async Task Main(string[] args)  
    {  
        // 假设我们有10个任务需要执行  
        var tasks = Enumerable.Range(1, 10).Select(async i =>  
        {  
            await semaphore.WaitAsync(); // 等待信号量可用  
            try  
            {  
                // 执行任务  
                Console.WriteLine($"任务 {i} 开始执行,当前时间:{DateTime.Now:HH:mm:ss.fff}");  
                await Task.Delay(1000); // 模拟耗时操作  
                Console.WriteLine($"任务 {i} 执行完成,当前时间:{DateTime.Now:HH:mm:ss.fff}");  
            }  
            finally  
            {  
                semaphore.Release(); // 释放信号量  
            }  
        }).ToList();  
  
        // 等待所有任务完成  
        await Task.WhenAll(tasks);  
  
        Console.WriteLine("所有任务执行完成。");  
    }  
}

         在上面这个例子中,我们创建了一个SemaphoreSlim实例,初始化为5,表示同时最多允许5个任务执行。

        然后,我们创建了10个任务,每个任务在执行前都会调用semaphore.WaitAsync()来等待信号量变得可用。当信号量可用时,任务会继续执行,并在执行完毕后通过semaphore.Release()释放信号量,以便其他任务可以执行。

        这种方法简单且有效,不需要我们深入了解TaskScheduler的内部实现,就可以轻松控制并发量。同时,它也避免了自定义TaskScheduler可能带来的复杂性和潜在的错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/782466.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

批量爬取B站网络视频信息

使用XPath爬取B站视频链接等相关信息 分析B站html框架获取内容完整代码 对于B站,目前网上的爬虫大多都是使用通过解析服务器的响应来爬取想要的内容,下面我们通过使用XPath来爬取B站上一些想要的信息 此次任务我们需要对B站搜索到的关键字,并…

本地多卡(3090)部署通义千问Qwen2-72B大模型提速实践:从龟速到够用

最近在做文本风格转化,涉及千万token级别的文本。想用大模型转写,在线的模型一来涉及数据隐私,二来又不想先垫钱再找报销。本地的7-9B小模型又感觉效果有限,正好实验室给俺配了4卡3090的机子,反正也就是做个推理&#…

Python falsk 接口挂载 步骤

Python falsk 接口挂载 步骤 1.首先要有自己独立的python环境,因为如果和别人共用环境的话,会有依赖包冲突的情况 2.找到python.exe的安装路径 3.CMD切换到该路径下 4.执行指令activate,进入到专属的python环境 5.然后执行指令 pip freeze > re.tet…

CentOS 7遗忘了root密码怎么办?

正文共:666 字 12 图,预估阅读时间:1 分钟 说来也巧,突然发现使用KVM在部署CentOS时(笔记本电脑安装CentOS系统),会有一个神奇的现象,还不是偶然出现的,在最近的三四次部…

【ComfyUI节点】扰动注意力引导Perturbed Attention Guidance

扰动注意力引导 Perturbed Attention Guidance GitHub - KU-CVLAB/Perturbed-Attention-Guidance: Official implementation of "Perturbed-Attention Guidance" 按照官方介绍,扰动注意力指导显著提高了扩散模型的样本质量,而无需外部条件&am…

测试用例编写与管理流程

hello,大家好,我是一名测试开发工程师,至今已在自动化测试领域深耕9个年头,现已将本人实战多年的多终端自动化测试框架【wyTest】开源啦,在接下来的一个月里,我将免费指导大家使用wyTest,请大家…

14-Django项目--文件上传-Excel

目录 前端 路由 视图函数 前端 <div class"modal-body"><form method"post" enctype"multipart/form-data" action"/pretty/asset/">{% csrf_token %}<input type"file" name"excel"><bu…

Leetcode3194. 最小元素和最大元素的最小平均值

Every day a Leetcode 题目来源&#xff1a;3194. 最小元素和最大元素的最小平均值 解法1&#xff1a;排序遍历 将数组 nums 排序后&#xff0c;利用双指针计算每一对 (minElement maxElement) / 2&#xff0c;最小值即为答案。 代码&#xff1a; /** lc appleetcode.cn …

Spring源码十七:Bean实例化入口探索

上一篇Spring源码十六&#xff1a;Bean名称转化我们讨论doGetBean的第一个方法transformedBeanName方法&#xff0c;了解Spring是如何处理特殊的beanName&#xff08;带&符号前缀&#xff09;与Spring的别名机制。今天我们继续往方法下面看&#xff1a; doGetBean 这个方法…

AI 大模型系统实战

AI 大模型是什么&#xff1f; 维基百科对基础模型的定义是这样的&#xff0c;基础模型是一种大型机器学习模型&#xff0c;通常在大量数据上进行大规模训练&#xff08;通过自监督学习或半监督学习&#xff09;&#xff0c;以使它可以适应各类下游任务。因此&#xff0c;它需要…

数学系C++ 类与对象 STL(九)

目录 目录 面向对象&#xff1a;py&#xff0c;c艹&#xff0c;Java都是,但c是面向过程 特征&#xff1a; 对象 内敛成员函数【是啥】&#xff1a; 构造函数和析构函数 构造函数 复制构造函数/拷贝构造函数&#xff1a; 【……】 实参与形参的传递方式&#xff1a;值…

【Java】了解异常

初始异常 我们平时应该已经接触过一些 “异常” 了&#xff0c;这里列举一些例子。 算术异常&#xff1a; 数组下标越界异常&#xff1a; 访问空指针异常&#xff1a; 所谓异常指的就是程序在 运行时 出现错误时通知调用者的一种机制。 异常的基本用法 捕获异常 try{ 有可能…

知识的向量表示

1、one-hot表示&#xff0c;空间太大 2、bag词袋模型&#xff0c;无法表示词的语义 3、词的语义由什么决定&#xff1f;词由他的上下文决定&#xff1f;分布式语义 4、CBow&#xff0c;通过前面几个词和后面几个词&#xff0c;预测中间几个词 5、skip-gram&#xff0c;通过…

【Python】已解决:(MongoDB安装报错)‘mongo’ 不是内部或外部命令,也不是可运行的程序

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例及解决方案五、注意事项 已解决&#xff1a;&#xff08;MongoDB安装报错&#xff09;‘mongo’ 不是内部或外部命令,也不是可运行的程序 一、分析问题背景 在安装和配置MongoDB时&#xff0c;有…

数据库逆向工程工具reverse_sql

reverse_sql 是一个用于解析和转换 MySQL 二进制日志&#xff08;binlog&#xff09;的工具。它可以将二进制日志文件中记录的数据库更改操作&#xff08;如插入、更新、删除&#xff09;转换为反向的 SQL 语句&#xff0c;以便对系统或人为产生的误操作进行数据回滚和恢复。 *…

Python28-9 XGBoost算法

XGBoost&#xff08;eXtreme Gradient Boosting&#xff0c;其正确拼写应该是 "Extreme Gradient Boosting"&#xff0c;而XGBoost 的作者在命名时故意使用了不规范的拼写&#xff0c;将“eXtreme”中的“X”大写&#xff0c;以突出其极限性能和效率&#xff09;是一…

【open3d专栏】利用PCA计算狭长点云的主方向

在点云处理中&#xff0c;PCA通常用于识别数据集中的主要方向&#xff0c;从而帮助理解数据的几何结构。 使用工具&#xff1a;python&#xff0c;open3d库 目的&#xff1a;计算狭长型点云的主方向 # -*- coding: utf-8 -*- """ Created on Sun Jul 7 11:50…

SpringMVC源码解析(一):web容器启动流程

SpringMVC源码系列文章 SpringMVC源码解析(一)&#xff1a;web容器启动流程 目录 一、SpringMVC全注解配置1、pom文件2、web容器初始化类(代替web.xml)3、SpringMVC配置类(代替springmvc.xml)4、测试Controller 二、SpringServletContainerInitializer1、web容器初始化入口2、…

RNN 交叉熵

RNN善于处理时序 序列数据 简单RNN 展开就是 LSTM 遗忘门f_t决定上期记忆保留多少 隐藏层 在神经网络中&#xff0c;隐藏层指的是除了输入层和输出层之外的层&#xff0c;它们的输出不会直接用于网络的最终输出&#xff0c;而是作为中间步骤用于提取和转换数据。因此&#x…

LabVIEW光谱测试系统

在现代光通信系统中&#xff0c;光谱分析是不可或缺的工具。开发了一种基于LabVIEW的高分辨率光谱测试系统&#xff0c;通过对可调谐激光器、可编程光滤波器和数据采集系统的控制&#xff0c;实现了高效、高精度的光谱测量。 项目背景 随着光通信技术的迅速发展&#xff0c;对…