C# 一个自己写的异步并行执行器
有的时候咱们需要循环执行业务,如果处理过程不是计算密集型,就可以使用多线程并行处理,这样能大幅度提高执行效率
最开始我是想着有没有现成的,结果找了半天没发现有现成的,于是就自己封装了一个,简单测试了一下发现没啥问题
异步并行执行器

/// <summary> /// 异步并行执行器,可以将任务并行执行,提高执行速度 /// </summary> public class AsyncParallelExecutor<T> { /// <summary> /// 对单一数据进行处理的业务逻辑委托 /// </summary> /// <param name="taskID">异步任务ID</param> /// <param name="index">进度索引</param> /// <param name="arg">参数</param> /// <returns>是否继续处理下一条</returns> public delegate Task<bool> ExecuteFunc(int taskID, int index, T arg); /// <summary> /// 数据的总数量 /// </summary> public readonly int TotalCount; readonly object _lock = new object(); readonly Queue<T> queue = new Queue<T>(); readonly ExecuteFunc _executeFunc; /// <summary> /// 传入参数集合和业务委托,创建一个异步并行执行器 /// </summary> /// <param name="args">参数集合</param> /// <param name="executeFunc">处理单位数据的业务委托</param> public AsyncParallelExecutor(IEnumerable<T> args, ExecuteFunc executeFunc) { foreach (var arg in args) { queue.Enqueue(arg); } TotalCount = queue.Count; _executeFunc = executeFunc; } /// <summary> /// 开始执行并行任务 /// </summary> /// <param name="taskCount">使用的异步任务个数</param> /// <returns></returns> public async Task Start(int taskCount = 2) { Task[] tasks = new Task[taskCount]; for (int i = 0; i < taskCount; i++) { tasks[i] = AsyncTask(i); } await Task.WhenAll(tasks); } Task AsyncTask(int taskID) { return Task.Run(async () => { while (true) { var (success, index) = TryGet(out T val); if (success == false) { break; } bool ret = await _executeFunc(taskID, index, val); if (ret == false) { break; } } }); } (bool success, int index) TryGet(out T val) { lock (_lock) { if (queue.Count > 0) { val = queue.Dequeue(); return (true, TotalCount - queue.Count); } else { val = default; return (false, TotalCount); } } } }
使用方法

AsyncParallelExecutor<int> ape; CancellationToken Token; public async Task Start() { var ps = Enumerable.Range(0, 20); //模拟要业务参数集合 ape = new AsyncParallelExecutor<int>(ps, Execute); await ape.Start(); } async Task<bool> Execute(int taskID, int index, int val) { if (Token.IsCancellationRequested) { return false; //中断操作 } Thread.Sleep(3000); //模拟毫时操作 Logger.Info($"任务ID={taskID},进度={index}/{ape.TotalCount},参数={val}"); await Task.CompletedTask; return true; }
需要注意的是,具体执行操作的方法是异步的,如果要统计数据,累加器记得用原子操作累加
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
2017-07-17 C#驱动mysql明明数值不为空却一直说DBNull.Value的诡异情况