重构《手搓》TaskFactory带你更安全的起飞
一、彻底的重构和优化
- 本次《手搓》TaskFactory的重构是直接把依赖的《手搓》线程池一起重构了
- 可以参看上一篇异步"伪线程"重构《手搓》线程池,支持任务清退
- 也就是说安全系数非常高,直接在线程里面处理
- 大家可以更安全更放心的起飞
二、先看一下同步任务取消的Case
1. 《手搓》TaskFactory手动取消同步任务
- 执行同步方法Hello
- 等待100毫秒后调用Cancel
- 等待117毫秒,触发异常
- 之后在另一个线程Hello还是执行了
- 如果方法已经执行很可能无法真实的取消(除非增加token参数来控制)
- 但Task已经反馈给调用方本次取消,不会继续等待
- 当前“线程”也回收了,避免由此可能导致的线程池堵塞
- 有人可能说,这有什么稀奇的,系统API就支持
var options = new TaskFactoryOptions { ConcurrencyLevel = 1 };
var factory = new ConcurrentTaskFactory(options);
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
var task = factory.StartNew(() => Hello("张三", 1000), tokenSource.Token);
Assert.NotNull(task);
await Task.Delay(100);
tokenSource.Cancel();
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
await Task.Delay(1000);void Hello(string name, int time = 10)
{Thread.Sleep(time);_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Hello {name},{DateTime.Now:HH:mm:ss.fff}");
}// Thread19 System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.ConcurrentTaskFactoryTests.ActionCancel() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\ConcurrentTaskFactoryTests.cs:line 90
// Thread19 Total Span :121.4448
// Thread11 Hello 张三,11:41:00.641
2. 系统TaskFactory手动取消任务
- 系统TaskFactory的流程和前面一样
- 也是执行同步方法Hello
- 等待100毫秒后调用Cancel
- 执行成功,共耗时1秒
- 是不是很魔幻,居然没取消
- 系统TaskFactory有Bug?
var factory = Task.Factory;
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
var task = factory.StartNew(() => Hello("张三", 1000), tokenSource.Token);
Assert.NotNull(task);
await Task.Delay(100);
tokenSource.Cancel();
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");// Thread10 Hello 张三,11:43:06.118
// Thread19 Total Span :1006.9077
3. 《手搓》TaskFactory设置超时Case
- 还是同步方法Hello
- 这次通过CancelAfter设置1秒超时
- 等待1秒触发异常
- 之后在另一个线程Hello还是执行了
- 也就是说《手搓》TaskFactory超时清退成功
var options = new TaskFactoryOptions { ConcurrencyLevel = 1 };
var factory = new ConcurrentTaskFactory(options);
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
tokenSource.CancelAfter(TimeSpan.FromSeconds(1));
var task = factory.StartNew(() => Hello("张三", 2000), tokenSource.Token);
Assert.NotNull(task);
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
await Task.Delay(1000);// Thread16 System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.ConcurrentTaskFactoryTests.ActionTimeout() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\ConcurrentTaskFactoryTests.cs:line 114
// Thread16 Total Span :1075.7213
// Thread11 Hello 张三,15:57:04.440
4. 系统TaskFactory设置超时Case
- 执行同步方法Hello
- 通过CancelAfter设置1秒超时
- 任务执行成功,耗时2秒
- 再次魔幻的结果,居然又没取消
- 系统TaskFactory有Bug?
var factory = Task.Factory;
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
tokenSource.CancelAfter(TimeSpan.FromSeconds(1));
var task = factory.StartNew(() => Hello("张三", 2000), tokenSource.Token);
Assert.NotNull(task);
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
sw.Stop();
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");// Thread10 Hello 张三,10:39:45.556
// Total Span :2017.2007
5. 系统TaskFactory修改再测
- 把Cancel提前到StartNew之前
- 这次耗时106毫秒,任务取消
- 原来系统TaskFactory是要添加任务的时候判断是否取消,而不是执行的时候
- 意外不意外,惊喜不惊喜
- 《手搓》TaskFactory是执行时判断是否取消
- 你满意系统TaskFactory的Cancel逻辑还是《手搓》TaskFactory
- 很长一段时间笔者都以为系统TaskFactory有Bug
- 原来是设计如此,终于破案了
var factory = Task.Factory;
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
tokenSource.Cancel();
var task = factory.StartNew(() => Hello("张三", 1000), tokenSource.Token);
Assert.NotNull(task);
await Task.Delay(100);
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
// System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.TaskFactoryTests.ActionCancel2() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\TaskFactoryTests.cs:line 69
// Total Span :106.1664
三、取消异步任务的Case
1. 《手搓》TaskFactory并发控制的Case
- ConcurrencyLevel设置为1,设置1秒超时
- 这个CancellationToken参数传给实际执行的异步方法同时也传给线程池
- 以便线程池及时处理并及时清理已经取消的任务
- 还起到双保险的作用
- 如果HelloAsync没有对CancellationToken做出正确的处理
- 调用者也会及时触发取消的异常
- 本次执行3个异步任务,每个500毫秒
- 耗时1秒,两个任务执行成功,并触发取消异常
- 第3个并未实际执行,这里要归功于token参数起到了拦截的作用
- 系统TaskFactory没有控制异步和并发的逻辑就不对比
var options = new TaskFactoryOptions { ConcurrencyLevel = 1 };
var factory = new ConcurrentTaskFactory(options);
var tokenSource = new CancellationTokenSource();
var sw = Stopwatch.StartNew();
tokenSource.CancelAfter(TimeSpan.FromSeconds(1));
var token = tokenSource.Token;
var task = factory.StartTask((t) => HelloAsync("张三", 500, t), token);
var task2 = factory.StartTask((t) => HelloAsync("李四", 500, t), token);
var task3 = factory.StartTask((t) => HelloAsync("王二", 500, t), token);
try
{await Task.WhenAll(task, task2, task3);sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
await Task.Delay(2000);async Task HelloAsync(string name, int time = 10, CancellationToken token = default)
{await Task.Delay(time, token);_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} HelloAsync {name},{DateTime.Now:HH:mm:ss.fff}");
}// Thread31 HelloAsync 张三,10:30:54.720
// Thread11 HelloAsync 李四,10:30:55.231
// System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.ConcurrentTaskFactoryTests.TaskCancel0() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\ConcurrentTaskFactoryTests.cs:line 126
// Total Span :1013.774
四、全局设置超时的Case
1. 同步任务无CancellationToken的Case
- ItemLife配置为1秒
- Hello实际需要2秒
- 调用等待1秒后触发取消异常,与ItemLife配置一致
- 同步任务清退成功
var options = new TaskFactoryOptions { ConcurrencyLevel = 1, ItemLife = TimeSpan.FromSeconds(1) };
var factory = new ConcurrentTaskFactory(options);
var sw = Stopwatch.StartNew();
var task = factory.StartNew(() => Hello("张三", 2000));
Assert.NotNull(task);
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
await Task.Delay(1000);// Thread16 System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.ConcurrentTaskFactoryTests.ActionItemLife() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\ConcurrentTaskFactoryTests.cs:line 35
// Thread16 Total Span :1016.3529
// Thread11 Hello 张三,16:09:49.847
2. 异步任务无CancellationToken的Case
- ItemLife配置为1秒
- HelloAsync实际需要2秒
- 调用等待1秒后触发取消异常,与ItemLife配置一致
- 异步任务也清退成功
- 由于本次没有给HelloAsync传token,虽然清退了,HelloAsync还是稍后在其他线程执行了
- 这个Case再次证明token参数的重要性,可以避免不必要的操作
var options = new TaskFactoryOptions { ConcurrencyLevel = 1, ItemLife = TimeSpan.FromSeconds(1) };
var factory = new ConcurrentTaskFactory(options);
var sw = Stopwatch.StartNew();
var task = factory.StartTask(() => HelloAsync("张三", 2000));
Assert.NotNull(task);
try
{await task;sw.Stop();
}
catch (Exception ex)
{sw.Stop();_output.WriteLine(($"Thread{Environment.CurrentManagedThreadId} {ex}"));
}
_output.WriteLine($"Thread{Environment.CurrentManagedThreadId} Total Span :{sw.Elapsed.TotalMilliseconds}");
await Task.Delay(2000);// Thread17 System.Threading.Tasks.TaskCanceledException: A task was canceled.
// at TaskTests.Tasks.ConcurrentTaskFactoryTests.TaskItemLife() in D:\projects\HandCore.net\UnitTests\TaskTests\Tasks\ConcurrentTaskFactoryTests.cs:line 65
// Thread17 Total Span :1020.1329
// Thread8 HelloAsync 张三,16:14:04.831
五、揭秘重构《手搓》TaskFactory
1. 前1版本《手搓》TaskFactory是基于并发配额控制
- 启动异步扣除并发配额
- 注册ContinueWith返还并发配额
- 参考以前的博文《手搓》TaskFactory带你安全的起飞
2. 重构《手搓》TaskFactory去掉了并发配额控制
- 去掉并发配额控制
- 异步线程直接在线程池里面await
- 线程池原生支持性能更好
- 线程池大小就是最好的并发控制,原生支持后并发配额完全不需要
六、总结
1. 《手搓》TaskFactory的作用
- 《手搓》TaskFactory的主要作用是并发控制
- .net实现异步多并发很容易,但是并发太大很容易失控
- 比如数据库连接过高、上游服务被打挂
- 为此很多人都把.net程序写成“单线程”模式
- 即使写成“单线程”模式依然避免不了上游资源被打挂的事故
- 通过《手搓》TaskFactory可以设置为全局模式,来管控某些某些资源的并发控制
- 同时程序改动极小
- 无论是同步操作还是异步都可以托管给《手搓》TaskFactory
- 也就是实现程序的异步多并发的起飞
- 加上CancellationToken和ItemLife可以保证线程池的不会被堵塞
- 安全高效的线程池助力.net程序安全的起飞
2. 《手搓》线程池的作用
- 其一支持《手搓》TaskFactory的执行处理
- 其二支持事件总线的事件派发
- 拿来做一个毫秒级的任务调度系统应该也没什么问题
3. CancellationToken
- 及时清退任务的关键之一是CancellationToken
- 特别是含await的异步方法
- 当await成功后很可能已经发生了线程切换,耗时更是不确定的因素
- 这时很可能要校验CancellationToken判断是否还有必要继续执行
- 多步骤逻辑耗时,每一步骤前也很可能需要判断是否还有必要继续执行后面的步骤
- 耗时循环,每次循环也很可能需要判断是否还有必要继续执行
- 在某些特殊情况,同步方法也可能有必要增加CancellationToken
- 给实际执行的方法传CancellationToken的同时传给《手搓》TaskFactory或者《手搓》线程池,可以实现双保险
4. ItemLife
- ItemLife是线程池兜底的安全机制
- 可以有效避免线程池被堵塞
- 特别是那些还没来得及加CancellationToken的祖传代码
好了,就介绍到这里,更多信息请查看源码库
源码托管地址: https://github.com/donetsoftwork/HandCore.net ,欢迎大家直接查看源码。
gitee同步更新:https://gitee.com/donetsoftwork/HandCore.net
如果大家喜欢请动动您发财的小手手帮忙点一下Star,谢谢!!!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/958368.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
2025年质量好的便携婴儿车推荐
2025年质量好的便携婴儿车推荐 随着现代家庭对育儿便捷性和安全性的需求不断提升,便携婴儿车成为越来越多父母的首选。2025年,市场上涌现出众多设计精良、功能强大的便携婴儿车品牌,它们不仅轻便易携,还融合了智能…
2025年靠谱的煤矿井下清淤机器人厂家最新权威实力榜
2025年靠谱的煤矿井下清淤机器人厂家最新权威实力榜 煤矿井下清淤作业环境复杂,存在高粉尘、高湿度、有毒有害气体等危险因素,传统人工清淤效率低且安全隐患大。随着智能化技术的快速发展,清淤机器人凭借高效、安全…
Huggingface 214页训练手册:揭秘构建世界级大语言模型的秘密 - AI
《The Smol Training Playbook: The Secrets to Building World-Class LLMs》由 Hugging Face 团队于 2025 年 10 月 30 日发布,详情见https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook,聚焦Smo…
2025年质量好的印字封箱胶带厂家最新TOP实力排行
2025年质量好的印字封箱胶带厂家最新TOP实力排行 在包装行业中,印字封箱胶带作为重要的包装耗材,其质量直接影响产品运输安全和品牌形象。随着市场竞争加剧,选择一家实力雄厚、产品质量可靠的胶带供应商至关重要。…
2025 年青岛民办学校最新推荐榜,聚焦办学质量与特色服务的优质教育品牌深度解析青岛小学民办学校/青岛初中民办学校推荐
引言
民办教育领域的快速发展为家庭提供了多元选择,但办学水平参差不齐让择校决策愈发困难。部分家长因缺乏权威评价依据,难以精准判断学校的教学实力与服务质量。为此,我们联合行业协会开展专项测评,采用 “四维评…
JSON-server 数据操作示例
JSON-server 数据操作示例
使用 JavaScript Fetch API 对 JSON-server 进行 CRUD 操作
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta nam…
2025年口碑好的针织网眼布最新TOP品牌厂家排行
2025年口碑好的针织网眼布最新TOP品牌厂家排行 针织网眼布因其透气性、弹性、耐用性等特性,在鞋材、服装、家纺、箱包等领域广泛应用。随着市场需求的增长,越来越多的企业专注于高品质网眼布的研发与生产。2025年,…
Python四大容器核心操作速查表(全面版)
Python四大容器核心操作速查表(全面版)
说明时间复杂度标注:O(1)=常数级(快),O(n)=线性级(随数据量增长),O(k)=取决于传入可迭代对象长度
🔴 不可变容器(元组)的增删改操作均为“间接实现”,直接操作会报…
2025年热门的工业盐烘干机品牌厂家排行榜
2025年热门的工业盐烘干机品牌厂家排行榜 工业盐烘干机是化工、食品、医药等行业中不可或缺的设备,其性能直接影响生产效率和产品质量。随着技术进步和环保要求的提高,高效节能、智能化的烘干设备成为市场主流。以下…
2025年优质的高阻隔贴体膜厂家最新TOP排行榜
2025年优质的高阻隔贴体膜厂家最新TOP排行榜 随着食品保鲜、医疗包装、工业防护等领域对高阻隔材料需求的快速增长,贴体膜作为包装行业的关键材料,其性能与品质直接影响产品的保质期和安全性。2025年,高阻隔贴体膜…
2025 年通风气楼源头厂家最新推荐排行榜:聚焦专业制造标杆企业,精选优质品牌助力选购中脊通风气楼/工业厂房通风气楼公司推荐
引言
近期,行业权威协会针对通风气楼领域开展专项测评,通过多维度严苛考核,发布了 2025 年通风气楼源头厂家最新推荐榜单。此次测评采用科学系统的方法,从技术实力、产品质量、服务水平、市场口碑四大核心维度入手…
2025年口碑好的防雷汇流箱品牌厂家排行榜
2025年口碑好的防雷汇流箱品牌厂家排行榜 随着光伏发电行业的快速发展,防雷汇流箱作为光伏发电系统中的关键设备,其性能和可靠性直接影响整个系统的安全与效率。2025年,市场上涌现出一批技术领先、质量可靠的防雷汇…
CF2164E 小结
这题就是昨天晚上 Golble Round 的 E,感觉这题还可以。
就是首先要观察到这个图的状态有可能不是一个欧拉图。所以你需要通过第二种操作来建一些虚边。然后对于每对虚点,计算答案。
首先这个考虑虚点的顺序和排列方式…
2025 密封胶条厂家最新推荐榜:高校合作 + 全流程质控,权威测评靠谱品牌盘点门窗密封胶条/三元乙丙密封胶条/汽车密封胶条公司推荐
引言
密封胶条作为多行业核心配套产品,其质量直接影响下游产品性能与安全,但市场仍存在原料劣质、性能不达标、服务滞后等问题。为精准指引采购决策,行业协会联合检测机构开展 2025 年度测评,涵盖 120 余家企业。测…
2025年比较好的新能源汽车直流接触器厂家最新权威实力榜
2025年比较好的新能源汽车直流接触器厂家最新权威实力榜随着新能源汽车行业的蓬勃发展,直流接触器作为电动汽车高压系统的关键部件,其市场需求呈现爆发式增长。直流接触器承担着电池系统与整车电路之间的连接与断开功…
2025年上海血管瘤医院联系电话推荐:瑞椿领衔权威榜单
在血管瘤这一特殊疾病面前,患者与家属最迫切的需求往往是“找到真正专业、随时能联系上的医院”。上海作为医疗资源高度集中的城市,机构众多,广告信息混杂,如何快速锁定口碑扎实、技术领先、电话畅通的医疗机构,成…
2025年热门的网架加工厂家推荐及采购参考
2025年热门的网架加工厂家推荐及采购参考 随着建筑行业的快速发展,网架结构因其轻量化、高强度、施工便捷等优势,广泛应用于体育场馆、工业厂房、机场航站楼等领域。选择一家技术实力强、口碑优良的网架加工厂家至关…
2025年评价高的煤矿道岔厂家最新推荐排行榜
2025年评价高的煤矿道岔厂家最新推荐排行榜 煤矿道岔作为矿山运输系统的关键设备,其质量与性能直接影响煤矿生产的安全性和效率。随着技术的不断进步,市场对道岔产品的精度、耐用性和智能化要求越来越高。2025年,经…
2025年上海血管瘤医院联系电话推荐:瑞椿领航五强精选
在上海这样一座医疗资源高度集中的城市,血管瘤虽属良性病变,却因常出现在新生儿及颜面、关节等关键部位,让家庭格外焦虑。家长与成年患者最关心的问题无外乎:哪家医院经验多、设备新、预约快、后续随访方便?2025年…
2025年靠谱的暗扣隐藏式家具拉手厂家最新TOP排行榜
2025年靠谱的暗扣隐藏式家具拉手厂家最新TOP排行榜 在现代家居设计中,暗扣隐藏式拉手凭借其简约美观、安全实用的特性,逐渐成为高端定制家具的首选配件。这类拉手不仅能提升家具的整体质感,还能避免凸起设计带来的…