简体   繁体   English

C#串行数据接收事件饿了

[英]C# Serial DataReceived event starved

I am building on top of an existing application and using the C# SerialPort class to handle data transactions over USB. 我在现有应用程序的基础上构建并使用C#SerialPort类来处理USB上的数据事务。 I've noticed that when the application spawns a number of long-running threads and does not specify them as long-running using the TaskCreation LongRunning option, these threads can temporarily starve the SerialPort DataReceived event and prevent it from triggering for some extended amount of time. 我注意到,当应用程序产生许多长时间运行的线程,并且未使用TaskCreation LongRunning选项将它们指定为长时间运行时,这些线程可以暂时使SerialPort DataReceived事件死机,并防止它触发一些扩展的时间。

Is this some fundamental result of the way in which C# handles thread management? 这是C#处理线程管理方式的一些根本结果吗?

Is there any way to increase the "priority" of the DataReceived event? 有什么方法可以增加DataReceived事件的“优先级”吗?

If not, would a "solution" be to have a constantly running thread that polls the serial port data flags rather than using the DataReceived event? 如果不是,那么“解决方案”是否应该有一个不断运行的线程来轮询串行端口数据标志,而不是使用DataReceived事件?

Thanks! 谢谢!

That is pretty fundamental, yes. 这是非常基本的,是的。 Your DataReceived event handler is called by a thread-pool thread. 您的DataReceived事件处理程序由线程池线程调用。 When you've got too many of them active for other purposes, like Tasks that are not LongRunning, then it can be a while before your event handler gets a shot at running. 如果您有许多活动出于其他目的而活动(例如非LongRunning的任务),那么可能要过一会儿,事件处理程序才能开始运行。 The normal operating system scheduling algorithm that boosts a thread's priority when it completes an I/O call is ineffective here, it only gets the tp thread scheduled efficiently :) 正常的操作系统调度算法在完成I / O调用时提高线程的优先级,在这里无效,它只能高效地调度tp线程:)

This is a fundamental fire-hose problem, you are expecting the machine to accomplish more work than it can perform. 这是一个基本的消防水带问题,您期望机器完成的工作超出其性能。 The ballpark way to know if you are doing it right is by looking at Task Manager. 了解任务是否正确的主要方法是查看任务管理器。 CPU usage should be pegged at 100%. CPU使用率应固定为100%。 If it is substantially less then you are not using the thread-pool efficiently, some tasks are hogging the pool but are not executing enough code, typically because they are waiting too much on a sync object or an I/O operation to complete. 如果它要少得多,则说明您没有有效地使用线程池, 某些任务正在占用池,但执行的代码不足,通常是因为它们在同步对象或I / O操作上等待的时间过多。 You ought to fix that, either by using a plain Thread or with TaskCreationOptions.LongRunning. 您应该通过使用纯线程或TaskCreationOptions.LongRunning来解决此问题。 ThreadPool.SetMinThreads() is often quoted as a quick fix, it is a dirty one. ThreadPool.SetMinThreads()通常被引用为一种快速修复方法,它是一个肮脏的方法。 Upgrading the machine spec, more cores, is a cleaner one. 升级机器规格,增加内核数量,是一种更清洁的方法。

There's an even simpler solution -- use the serial port the way the device driver writers intended. 有一个甚至更简单的解决方案-按照设备驱动程序编写者的预期方式使用串行端口。 There is absolutely nothing about serial port communications that warrants use of a worker thread, either manually created or from the thread pool. 串行端口通信绝对不保证使用人工创建的线程或从线程池使用的工作线程。 I encourage you to read my entire blog post "If you must use .NET System.IO.Ports.SerialPort" , but the short version is to use BaseStream.ReadAsync with async + await if you are on a recent version of .NET, and BaseStream.BeginRead with a callback otherwise. 我鼓励您阅读我的整个博客文章“如果必须使用.NET System.IO.Ports.SerialPort” ,但是简短的版本是将BaseStream.ReadAsyncasync + await一起使用,如果您使用的是.NET的最新版本,和BaseStream.BeginRead ,否则带有回调。

Also, thanks for providing me with yet another reason the DataReceived event is horrible. 另外,感谢您为我提供DataReceived事件令人恐怖的另一个原因。 The list is getting quite long. 清单越来越长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM