Ver*_*rax 5 .net multithreading task threadpool
我在C#.Net 4.0应用程序中使用SerialPort类和s ThreadPool.QueueUserWorkItem或者Tasks 遇到了一个有趣的问题.
如果我同时使用2个或更多SerialPort,则只会出现此问题.每个串口都在自己的线程中运行,我以3种方式之一创建:
new Thread(DoSerialCommX)ThreadPool.QueueUserWorkItem(DoSerialCommX)new Task(DoSerialCommX, TaskCreationOptions.LongRunning).Start()为了说明这个问题,我创建了我的DoSerialCommX方法来永久地在循环中读取和写入串行端口.它看起来像这样:(我实际上并没有在我的真实程序中执行此操作.这只是我的测试程序中的一个片段,它隔离并说明了问题).
private void DoSerialCommX()
{
SerialPort port = new SerialPort("ComX", 9600);
port.Open();
while(true)
{
//Read and write to serial port
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用方法2或3,串行通信口吃,我收到很多通信超时.如果我使用方法1,一切都很好.此外,我应该提到这似乎只发生在我的基于英特尔凌动的PC上.台式电脑似乎没有问题.
我知道线程池重用了线程,默认情况下Task使用线程池.我知道线程池真正用于短期操作.但我尝试使用TaskCreationOptions.LongRunning,我认为会产生一个专用线程,而不是使用线程池,但它仍然无法正常工作.
所以这个问题: 是什么让Thread在这种情况下如此特别?有什么东西Thread使它更适合IO操作吗?
编辑:
到目前为止,答案似乎假设我正在尝试使用ThreadPool或任务进行永无止境的过程.在我的实际应用中,情况并非如此.我只是在上面的代码中使用了一个永无止境的循环来说明问题.我真的需要知道为什么Thread有效ThreadPool,Task有无.什么在技术上不同会导致串行通信打嗝?
从理论上讲,1、2 和 3 之间执行线程的行为方式几乎没有什么区别。它们都共享相同的默认执行优先级,除非您覆盖它 - 理论上线程调度程序将使用相同的策略来调度它们。他们都会高兴地坐在圆圈里旋转。
我怀疑方法之间更大的区别是:
从功能的角度来看,使用方法 2 和 3 有点滥用 - 您的意图是永远不退出该方法。这些策略针对原子、有限操作以及通常适合 IO 完成端口任务(例如异步网络、磁盘操作等)的无引导执行进行了优化...(也许您的串行端口代码也有可能?)
除非您有兴趣适应异步 IO,否则我会跳过 2 和 3。专注于线程 - 似乎您想要更细粒度、可预测的执行控制,而不需要线程池带来的基础设施开销。