C#串行数据接收事件匮乏
本文关键字:事件 数据 | 更新日期: 2023-09-27 18:26:01
我在现有应用程序的基础上构建,并使用C#串行端口类通过USB处理数据事务。我注意到,当应用程序生成了许多长时间运行的线程,并且没有使用TaskCreation LongRunning选项将其指定为长时间运行时,这些线程可能会暂时使SerialPort DataReceived事件处于饥饿状态,并在较长的时间内阻止其触发。
这是C#处理线程管理方式的一些基本结果吗?
是否有任何方法可以提高DataReceived事件的"优先级"?
如果没有,"解决方案"是让一个不断运行的线程轮询串行端口数据标志,而不是使用DataReceived事件吗?
谢谢!
这是非常基本的。DataReceived事件处理程序由线程池线程调用。当你有太多的活动任务用于其他目的时,比如不是LongRunning的任务,那么你的事件处理程序可能需要一段时间才能开始运行。在完成I/O调用时提高线程优先级的普通操作系统调度算法在这里是无效的,它只有效地调度tp线程:)
这是一个基本的消防软管问题,你期望机器完成比它能完成的更多的工作。要想知道你做得是否正确,最简单的方法就是看看任务经理。CPU使用率应固定在100%。如果它明显不足,则说明您没有有效地使用线程池,一些任务占用了线程池,但没有执行足够的代码,通常是因为它们在同步对象或I/O操作上等待太多才能完成。你应该通过使用普通线程或使用TaskCreationOptions.LongRuning.ThreadPool.SetMinThreads()来解决这个问题。它经常被引用为快速修复程序,这是一个肮脏的修复程序。升级机器规格,增加核心,是一个更清洁的过程。
还有一个更简单的解决方案——按照设备驱动程序编写器的意图使用串行端口。串行端口通信绝对不能保证使用工作线程,无论是手动创建的还是从线程池中创建的。我鼓励你阅读我的整篇博客文章"如果你必须使用.NET System.IO.Ports.SerialPort",但简短的版本是,如果你使用的是最新版本的.NET,则使用BaseStream.ReadAsync
和async
+await
,否则使用带回调的BaseStream.BeginRead
。
此外,感谢你为我提供了DataReceived
事件可怕的另一个原因。名单越来越长了。