当前位置: 首页 > news >正文

c# TaskScheduler

这里记录下 TaskScheduler 的简单用法。

使用场景:

使用 Task 的时候,大家知道用 TaskFactory.StartNew 可以用来创建一个 Task 。这里如果创建了 3 个,那么这3个 Task 就各自放飞直接运行了。

class Program
{private static TaskFactory _taskFactory;static void Main(string[] args){_taskFactory = new TaskFactory();_taskFactory.StartNew(Func1);_taskFactory.StartNew(Func2);_taskFactory.StartNew(Func3);Console.ReadLine();}static void Func1(){Thread.Sleep(3000);Console.WriteLine("Func1");}static void Func2(){Thread.Sleep(2000);Console.WriteLine("Func2");}static void Func3(){Thread.Sleep(1000);Console.WriteLine("Func3");}
}

结果:
Func3
Func2
Func1

一般情况下没什么大问题,但如果这3个中的每个Task都非常耗CPU或者内存,而计算机又需要预留资源去干别的事情,这就要让3个Task不能同时执行。又或者确实要让某些Task先做,有些后做。这就需要我们自己能够决定Task执行顺序。

怎样达到这样的效果?

答案就是:TaskScheduler,它可以让已经创建好的 Task 去按照特殊的顺序来执行。

就拿上面的场景来举例:
为了节约系统资源,我要让这3个Task单独执行,有一个在执行,其它俩就不能执行。最简单的就是串行执行,这样只需要写一个类继承TaskScheduler:

public class MyTaskScheduler : TaskScheduler, IDisposable
{private static readonly object _mutex = new object();public readonly List<Task> _currentTasks = new List<Task>();private readonly ManualResetEvent[] _schedulerEvents = new ManualResetEvent[2];public override int MaximumConcurrencyLevel => 1;public MyTaskScheduler(){_schedulerEvents[0] = new ManualResetEvent(false);_schedulerEvents[1] = new ManualResetEvent(false);var executionThread = new Thread(ExecutionThread) { Name = "MyThread" };executionThread.SetApartmentState(ApartmentState.MTA);executionThread.IsBackground = true;executionThread.Priority = ThreadPriority.Normal;executionThread.Start(null);}public void Dispose(){_schedulerEvents[1].Set();}private void ExecutionThread(object args){try{while (true){if (!WaitIfEmpty()){break;}Task task;lock (_mutex){task = _currentTasks[0];}try{TryExecuteTask(task);}catch (Exception){throw;}finally{TryDequeue(task);}}}finally{//todo}}private bool WaitIfEmpty(){lock (_mutex){if (_currentTasks.Count == 0){//pause task_schedulerEvents[0].Reset();}}//wait any signal.int id = WaitHandle.WaitAny(_schedulerEvents);// id is item index of _schedulerEventsreturn id == 0;}protected override IEnumerable<Task>? GetScheduledTasks(){lock (_mutex){return _currentTasks.ToArray();}}protected override void QueueTask(Task task){lock (_mutex){_currentTasks.Add(task);if (_currentTasks.Count > 0){// Start task_schedulerEvents[0].Set();}}}protected sealed override bool TryDequeue(Task task){lock (_mutex){var res = _currentTasks.Remove(task);return res;}}protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued){return false;}
}

运行结果:
Func1
Func2
Func3

在MyTaskScheduler 中,我建了一个线程 executionThread,线程方法是一个while循环,一直在监听有没有新的Task过来,有多个Task过来,就按Task创建顺序执行,没有的话 while 就暂停在 waitany 处。

这样的场景,配合 ManualResetEvent 和Task的CancellationTokenSource 非常适合做 带有暂停和取消功能的任务列表。

http://www.lryc.cn/news/502809.html

相关文章:

  • 可视化数据
  • 【Redis】Redis缓存击穿
  • 厦门凯酷全科技有限公司深耕抖音电商运营
  • 六西格玛DMAIC在企业得项目管理中有什么作用
  • vscode借助插件调试OpenFoam的正确的.vscode配置文件
  • SpringBoot整合JWT(JSON Web Token)生成token与验证
  • 把帕拉丁需要的.rom文件转成.bin
  • Nginx 缓存那些事儿:原理、配置和最佳实践
  • vue发展史
  • 基于Java和Vue开发的校园跑腿软件校园跑腿小程序系统源码
  • MySQL(五)--- 事务
  • llm chat场景下的数据同步
  • 机器学习经典算法
  • Scala中的泛型
  • 数据分析特征标准化方法及其Python实现
  • UnityShaderLab 实现程序化形状(一)
  • 前端数据安全防护(控制台)
  • 自己玩虚拟机:vagrant,virtual box,centos
  • Frida框架HOOK RegisterNatives函数
  • [创业之路-189]:《华为战略管理法-DSTE实战体系》-2- 生存与发展的双重旋律:短期与长期、战术与战略的交响乐章
  • TDengine 部署
  • 【前端】20种 Button 样式
  • 机器人构建详解:售前售后服务客服机器人与广告生成机器人的微调数据处理方法
  • mysql的执行计划分析和索引下推以及索引长度计算
  • C#中的string操作详解-截取、分割、连接、替换等
  • Redis Cluster 分片机制
  • 论文结论:GPTs and Hallucination Why do large language models hallucinate
  • CSS在线格式化 - 加菲工具
  • 组件通信(父传子,子传父,跨组件通信)
  • JWT 令牌:原理、应用与安全考量