需要一种替代方法来获得20毫秒的分辨率周期
本文关键字:20毫 周期 分辨率 方法 一种 | 更新日期: 2023-09-27 18:20:32
我需要在每个20ms
读取来自CAN
网络的消息。为此,我制作了一个函数,其工作原理如下所述。这是一种变通办法,但确实有效。
public void Read_CAN_RC_Message()
{
bool a = true;
while (a)
{
Stopwatch t = Stopwatch.StartNew();
// My actual Function Starts Here
int rMulti = CANbus.CAN_Receive_multiple_nonblock(recieveMsg, 5);
if (0 < rMulti)
{
count++;
for (int k = 0; k < rMulti; k++)
{
if (recieveMsg[k].id == 0x400)
{
currentX = 0;
currentY = 0;
currentX = currentX | recieveMsg[k].data[3];
currentX = (currentX << 8) | recieveMsg[k].data[2];
currentX = (currentX << 8) | recieveMsg[k].data[1];
currentX = (currentX << 8) | recieveMsg[k].data[0];
currentY = currentY | recieveMsg[k].data[7];
currentY = (currentY << 8) | recieveMsg[k].data[6];
currentY = (currentY << 8) | recieveMsg[k].data[5];
currentY = (currentY << 8) | recieveMsg[k].data[4];
}
// Function Ends here
int timestep = t.Elapsed.Milliseconds; // To measure Time Needded to complete the Operation
timeCheck.Rows.Add(timestep,str);
}
while (t.Elapsed < timer20ms)
{
// Nothing
}
}
}
我很快意识到,操作需要2ms
才能完成,而对于剩余的18ms
,我的处理器陷入了无限循环。因此,此操作需要其自己的独立线程,该线程始终可以工作(使用处理器)。有没有一种更整洁、更专业的方法可以做到这一点。请提出建议。我需要在一个单独的线程中运行这个应用程序,因为它必须始终在应用程序启动后运行,直到关闭。
使用Timer类。你可以让它每20ms调用你的函数。
https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx
您可以将Timer与20ms Timer_Elpased一起使用。或者你可以让你的线程处于睡眠模式15-20毫秒。线程睡眠(20)
我在其他网站上找到了一个解决方案。我正在放置链接,我已经测试过了,它的效果非常好http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer希望它将来能帮助人们。谢谢你的帮助。真的很感激@idstam谢谢你给我发MSDN链接。它教会了我一两件事。
在设备定期发送数据的情况下,必须使用异步方式来获取数据。
要为您提供完整的解决方案或建议,请显示CANbus dll的完整合同。
此外,如果你解释一下主要任务会更好。
我推荐Thread.Sleep
和一些额外的技巧:
-
请求高计时器分辨率:MSDN:获取和设置计时器分辨率。你可能可以在pinvoke.net 上找到C#签名
-
使用
Stopwatch
类来计算等待期的长度。如果周期小于1ms,请不要呼叫"睡眠"。 -
使用
Thread
类提高线程优先级 -
如果可能的话,在另一个线程上进行昂贵的计算。
-
可选:线程后使用忙等待。睡眠最长1毫秒以获得更好的价格。使用Thread.Spin等待。
组合用1。和2。给了我足够的精度,可以在不造成卡顿/滞后的情况下为游戏执行帧制动。