【发布时间】:2010-05-28 11:47:57
【问题描述】:
我的 C# 应用程序从特殊的 USB 设备读取数据。数据被读取为所谓的“消息”,每个消息都有 24 个字节。每秒必须读取的消息量可能不同(最大频率相当高,大约每秒 700 条消息),但应用程序必须全部读取。
读取消息的唯一方法是调用函数“ReadMessage”,该函数返回从设备读取的一条消息。该函数来自外部 DLL,我无法修改它。
我的解决方案:我有一个单独的线程,它在程序运行期间一直在运行,唯一的工作就是循环读取消息。然后在主应用程序线程中处理接收到的消息。
“读取线程”中执行的函数如下:
private void ReadingThreadFunction() {
int cycleCount;
try {
while (this.keepReceivingMessages) {
cycleCount++;
TRxMsg receivedMessage;
ReadMessage(devHandle, out receivedMessage);
//...do something with the message...
}
}
catch {
//... catch exception if reading failed...
}
}
此解决方案运行良好,所有消息均已正确接收。但是,应用程序消耗太多资源,我的电脑的 CPU 运行在 80% 以上。因此我想减少它。
感谢“cycleCount”变量,我知道线程的“循环速度”约为每秒 40 000 个循环。这是不必要的太多,因为我需要接收最多 700 条消息/秒。 (并且设备有大约 100 条消息的缓冲区,因此循环速度可以更低一些)
我试图通过 Thread.Sleep(1) 将线程挂起 1 毫秒来降低循环速度;命令。当然,这不起作用,循环速度变成了大约 70 循环/秒,这不足以读取所有消息。我知道这种尝试很愚蠢,让线程进入睡眠状态然后唤醒他需要的时间远超过 1 毫秒。
但是,我不知道还能做什么:除了 Thread.Sleep 之外,还有其他方法可以减慢线程执行速度(以减少 CPU 消耗)吗?还是我完全错了,我应该为这个任务使用不同的东西而不是 Thread,也许是 Threading.Timer 或 ThreadPool?
非常感谢您提出的所有建议。这是我在这里的第一个问题,我是使用线程的初学者,所以如果不够清楚,请原谅。
【问题讨论】:
-
ReadMessage 是阻塞还是非阻塞?
-
正确的方法是使设备驱动程序中断驱动。我猜硬件制造商在那里失败了。
-
以下所有基于 1ms sleep 的解决方案请注意系统分辨率一般为 15-16ms,更改请看stackoverflow.com/a/15071477。
标签: c# multithreading