0

0

c# 如何用 EventSource 和 EventListener 监控内部并发事件

煙雲

煙雲

发布时间:2026-01-15 09:58:47

|

168人浏览过

|

来源于php中文网

原创

EventSource 是 .NET 轻量级事件发布机制,只负责“写”;EventListener 是抽象基类,不可直接实例化,必须继承并重写 OnEventSourceCreated 和 OnEventWritten 才能接收事件。

c# 如何用 eventsource 和 eventlistener 监控内部并发事件

EventSource 是什么,为什么不能直接 new EventListener

EventSource 是 .NET 提供的轻量级、高性能事件发布机制,专为生产环境诊断设计;它本身不负责监听,只负责「写」。而 EventListener 是抽象基类,必须继承并重写 OnEventSourceCreatedOnEventWritten 才能接收事件——你不能直接 new EventListener(),否则毫无作用。

如何让自定义 EventListener 捕获并发相关事件(如 TaskScheduler、ThreadPool)

.NET 运行时自带多个内部 EventSource,比如 System.Threading.Tasks.TplEventSourceSystem.Runtime.ThreadPoolEventSource,它们默认是禁用的。要监听,必须在 OnEventSourceCreated 中显式启用对应事件源,并指定关键词(keyword)和等级(level)。

  • 关键词决定捕获哪类事件:例如 TaskScheduler 事件常用 EventSource.Settings.TaskScheduler(实际值为 0x10),ThreadPoolEventSource.Settings.ThreadPool(0x20)
  • 等级至少设为 EventLevel.Verbose 才能看到调度细节(如任务入队、线程唤醒)
  • 必须调用 EnableEvents(eventSource, level, keywords),且该调用需在 OnEventSourceCreated 内完成,延迟启用会丢事件
public class ConcurrencyEventListener : EventListener
{
    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        if (eventSource.Name == "System.Threading.Tasks.TplEventSource")
        {
            EnableEvents(eventSource, EventLevel.Verbose, (EventKeywords)0x10); // TaskScheduler
        }
        else if (eventSource.Name == "System.Runtime.ThreadPoolEventSource")
        {
            EnableEvents(eventSource, EventLevel.Verbose, (EventKeywords)0x20); // ThreadPool
        }
    }

    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        if (eventData.EventName is "ScheduledTask" or "ThreadRequested" or "WorkerThreadStart")
        {
            Console.WriteLine($"[{eventData.EventSource.Name}] {eventData.EventName}: {string.Join(", ", eventData.PayloadNames.Zip(eventData.Payload, (n, v) => $"{n}={v}"))}");
        }
    }
}

常见漏掉的并发事件和调试陷阱

很多人以为启用了 TplEventSource 就能看见所有 Task 行为,但实际有三个关键限制:

  • TaskCreationOptions.RunContinuationsAsynchronouslyTask.Run 创建的任务才触发 ScheduledTask;同步 continuation(如 ContinueWith 默认行为)不会发事件
  • ThreadPoolEventSourceThreadRequested 只在“线程不足需扩容”时发出,空闲线程复用过程无事件
  • 若程序启动后才创建 ConcurrencyEventListener 实例,此前已发生的调度事件(尤其是 AppDomain 初始化阶段的)完全丢失——必须尽早 new 并保持存活
  • 事件负载高时(如每秒数千任务),OnEventWritten 是同步调用,阻塞会导致事件被丢弃;生产环境应异步缓冲或限流处理

验证是否真收到了并发事件的最简方法

不要依赖日志滚动——写个可复现的最小触发片段,配合断点或计数器确认:

Audo Studio
Audo Studio

AI音频清洗工具(噪音消除、声音平衡、音量调节)

下载
var listener = new ConcurrencyEventListener();
// 确保 listener 实例不被 GC(比如存为 static 字段)

Task.Run(() => Thread.Sleep(1)); // 触发 ThreadPool + Tpl 调度事件
Task.Factory.StartNew(() => { }, TaskCreationOptions.PreferFairness);

// 等待一小会儿再 Dispose,避免事件还在管道中
await Task.Delay(100);
listener.Dispose();

如果 OnEventWritten 完全没被调用,优先检查 EventSource.Name 是否拼错(大小写敏感)、.NET 版本是否支持(TplEventSource 在 .NET Core 2.1+ 稳定,.NET Framework 4.6.2+ 有但字段名不同)。

并发监控不是开箱即用的开关,每个 EventSource 都有自己隐含的触发边界和采样逻辑,想看到某类行为,得先确认它确实属于该事件源的输出范畴。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

56

2026.01.21

三角洲入口地址合集
三角洲入口地址合集

本专题整合了三角洲入口地址合集,阅读专题下面的文章了解更多详细内容。

28

2026.01.21

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

378

2026.01.21

妖精漫画入口地址合集
妖精漫画入口地址合集

本专题整合了妖精漫画入口地址合集,阅读专题下面的文章了解更多详细内容。

115

2026.01.21

java版本选择建议
java版本选择建议

本专题整合了java版本相关合集,阅读专题下面的文章了解更多详细内容。

3

2026.01.21

Java编译相关教程合集
Java编译相关教程合集

本专题整合了Java编译相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

9

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 49.4万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号