我在使用C# .Net 4.0应用程序的SerialPort类以及ThreadPool.QueueUserWorkItem或Tasks时遇到了有趣的问题。
仅当我同时使用2个或更多SerialPorts时才会出现问题。每个串口在自己的线程中运行,我可以通过以下3种方式之一创建线程:
1. new Thread(DoSerialCommX) 2. ThreadPool.QueueUserWorkItem(DoSerialCommX) 3. new Task(DoSerialCommX, TaskCreationOptions.LongRunning).Start()
为了说明这个问题,我创建了一个DoSerialCommX方法,在循环中永远读写串口。代码大致如下:(这不是我的真实程序,而是从测试程序中隔离和说明该问题的片段)
如果我使用方法2或3,串行通信就会出现卡顿,并且我会收到很多通信超时的错误。如果我使用方法1,一切都很好。此外,我应该提到,这似乎只发生在我的Intel Atom台式电脑上。桌面PC没有问题。
我知道线程池会重用线程,默认情况下,Task使用线程池。我知道线程池真正意图是为短期操作而设计的。但是我尝试使用TaskCreationOptions.LongRunning,我认为它会生成一个专用线程而不是使用线程池,但仍然无法解决问题。
所以问题是:在这种情况下,什么使“线程”如此特殊?有关“线程”的某些内容使其更适合IO操作吗?
编辑:到目前为止,答案似乎假定我正在尝试将ThreadPool或Tasks用于永无止境的过程。在我的实际应用程序中,情况并非如此。我只是在上面的代码中使用永无止境的循环来说明问题。我真的需要知道为什么“线程”有效,而“ThreadPool”和“Task”则不行。从技术上讲,它们之间有什么不同会导致串行通信出现问题?
仅当我同时使用2个或更多SerialPorts时才会出现问题。每个串口在自己的线程中运行,我可以通过以下3种方式之一创建线程:
1. new Thread(DoSerialCommX) 2. ThreadPool.QueueUserWorkItem(DoSerialCommX) 3. 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
}
}
如果我使用方法2或3,串行通信就会出现卡顿,并且我会收到很多通信超时的错误。如果我使用方法1,一切都很好。此外,我应该提到,这似乎只发生在我的Intel Atom台式电脑上。桌面PC没有问题。
我知道线程池会重用线程,默认情况下,Task使用线程池。我知道线程池真正意图是为短期操作而设计的。但是我尝试使用TaskCreationOptions.LongRunning,我认为它会生成一个专用线程而不是使用线程池,但仍然无法解决问题。
所以问题是:在这种情况下,什么使“线程”如此特殊?有关“线程”的某些内容使其更适合IO操作吗?
编辑:到目前为止,答案似乎假定我正在尝试将ThreadPool或Tasks用于永无止境的过程。在我的实际应用程序中,情况并非如此。我只是在上面的代码中使用永无止境的循环来说明问题。我真的需要知道为什么“线程”有效,而“ThreadPool”和“Task”则不行。从技术上讲,它们之间有什么不同会导致串行通信出现问题?