C# 实现上位机5ms定时,精度波动在几十微秒。

在最近做的一个项目上,上位机需要定时的发送采集指令到硬件,采集的频率为5ms。采用了线程池多线程处理数据,但是使用定时器Timer空间和Thread.sleep(5)都没能实现。出现了在部分时间点上能够达到要求,部分点的间隔达到了15.6毫秒,远达不到技术要求。为了解决这一问题,查询了大量的资料。怀疑这个与windows系统的cpu时间分配方式和线程沉睡后的唤醒有关。简单的讲一下,windows采用的是抢占式的时间分配,系统会根据每个线程的优先等级和线程运行时间计算出下一个运行的线程。当线程t1被唤醒时,不会立即执行而是先等当前在执行的线程tc的时间片结束后再和所有的线程一起计算出cpu下一个时间片执行的线程。这应该就是导致为什么会出现部分时间点间隔为5毫秒,部分时间间隔远大于5毫秒。

解决这个问题,采用了Thread.sleep(0)这个方法,其意思是重新计算线程的优先等级。在代码中多处添加该语句使程序cpu能够经常访问时间对比语句。

代码如下,两种方法都可以实现

在方法二中做了改进,加入了一个沉睡三秒语句,其中用是避免时间比较大量的占用线程时间。

还有可以通过调用windows的API实现。

        方法一:
        [DllImport("winmm")]
        static extern uint timeGetTime();

        [DllImport("winmm")]
        static extern void timeBeginPeriod(int t);

        [DllImport("winmm")]
        static extern uint timeEndPeriod(int t);


        private void timer()   //调用API
        {
            uint timerstart = timeGetTime();
            while (true)
            {
                uint i = 0;
                while (i < 5)     //N为时间间隔(ms)
                {
                    i = timeGetTime() - timerstart;
                }
                timerstart = timeGetTime();
                sendMsg();               //需要循环运行的函数;           
            }
        }
        方法二:
        private void timer_()   //使用DateTime类
        {
            long lt1 = DateTime.Now.ToFileTime();//取当前时间

            while (true)
            {
                long lt = 0;
                while (lt < 50000)     //N为时间间隔(0.1us)
                {
                    long lt2 = DateTime.Now.ToFileTime();
                    lt = lt2 - lt1;
                    if (lt < 100)
                    {
                        Thread.Sleep(3);
                    }
                }
                //Console.WriteLine(lt);
                lt1 = DateTime.Now.ToFileTime();
                sendMsg();               //需要循环运行的函数;           
            }
        }

参考资料

https://www.jianshu.com/p/9cf4a0dcb3b5

https://zhidao.baidu.com/question/1900127035845621380.html

https://blog.csdn.net/lgstudyvc/article/details/9337063

如有问题,欢迎指正。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
指数平滑法的计算中,关键是α的取值大小,但α的取值又容易受主观影响,因此合理确定α的取值方法十分重要,一般来说,如果数据波动较大,α值应取大一些,可以增加近期数据对预测结果的影响。如果数据波动平稳,α值应取小一些。理论界一般认为有以下方法可供选择:    经验判断法。这种方法主要依赖于时间序列的发展趋势和预测者的经验做出判断。   1、当时间序列呈现较稳定的水平趋势时,应选较小的α值,一般可在0.05~0.20之间取值;   2、当时间序列有波动,但长期趋势变化不大时,可选稍大的α值,常在0.1~0.4之间取值;   3、当时间序列波动很大,长期趋势变化幅度较大,呈现明显且迅速的上升或下降趋势时,宜选择较大的α值,如可在0.6~0.8间选值,以使预测模型灵敏度高些,能迅速跟上数据的变化;   4、当时间序列数据是上升(或下降)的发展趋势类型,α应取较大的值,在0.6~1之间。   试算法。根据具体时间序列情况,参照经验判断法,来大致确定额定的取值范围,然后取几个α值进行试算,比较不同α值下的预测标准误差,选取预测标准误差最小的α。   在实际应用中预测者应结合对预测对象的变化规律做出定性判断且计算预测误差,并要考虑到预测灵敏度和预测精度是相互矛盾的,必须给予二者一定的考虑,采用折中的α值。 下期预测数=本期实际数×平滑系数+本期预测数×(1-平滑系数) 如某种产品销售量的平滑系数为0.4,1996年实际销售量为31万件,预测销售量为33万件。则1997年的预测销售量为: 1997年预测销售量= 31万件×0.4+33万件×(1-0.4)=32.2万件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值