C#中Timer实现Tick使用精度的问题

目录

Timer实现Tick使用精度

实现效果

实现误区

解决思路

效率

三种Timer组件的区别

1. System.Windows.Forms.Timer  

2. System.Timers.Timer 基于服务

3. System.Threading.Timer 基于线程

Timer实现Tick使用精度

我们想在C#中实现一秒钟执行n次的一个事件,然后其他方法可以监听这个事件,最终实现每一帧随着Tick改变,我们的倒计时开始计数.

在使用Timer过程中发现Timer的精度有问题,最高频率是1秒调用62次,不满足我们的使用需求,100帧每秒,于是我们采用了别的方式实现这样的功能

实现效果

实现误区

我们最早实现方法是直接开启一个新线程,在线程内部开启一个Timer,设定Timer的延迟,但是最终发现它的执行精度最高只能达到62帧每秒,我就算把Timer的间隔时间设置为1ms也是只能执行62帧每秒,原因我们初步推测是因为Timer的精度不足.

解决思路

于是我们前往了C#源码查看,发现源码是通过Stopwatch实现的Timer类,Stopwatch类主要是一个倒计时秒表,既然知道是什么东西了那么就好实现了,我们开启一个新线程,保证线程一直执行就加上无限循环while(true). 在外部 我们开启Stopwatch,然后我们在while中判断秒表是否达到我们的需求,如果达到了那么就调用一个事件,然后在外部监听这个事件,就可以实现了

代码片段

class Program { /// <summary> /// 10ms trigger ont time /// </summary> private const int tickTime = 10; private static Action<long> Tick; static void Main(string[] args) { Tick += (x) => { Console.WriteLine("Time:" + x); }; Thread t = new Thread(() => { Stopwatch s = new Stopwatch(); s.Start(); long temp = 0; while (true) { if (s.ElapsedMilliseconds >= temp + 10) { temp = s.ElapsedMilliseconds; Tick?.Invoke(temp); } } }); t.IsBackground = true; t.Start(); while (true) { } } } 效率

测试上述代码后发现,设定为10ms执行一次的,按照理论上执行次数是1秒钟100帧,但实际效果是90帧,于是我们得出结论,使用这种方式在10ms的时候,效率是90%,然后我们测试了1ms执行一次的效果,效率为50%,也就是1秒钟执行了500次.

三种Timer组件的区别

timer计时器,每隔间隔的时间就会触发事件。  

1. System.Windows.Forms.Timer  

--应用于Windows应用程序,基于UI,独占一个线程。

--属性 interval:时间间隔  ms

--事件 Tick事件,如果在此事件中执行的任务过多,会发生阻塞。

--应用 主要应用修改UI元素(窗体的窗体属性)

--注意事项 如果单次执行时间超过设置的间隔时间,会影响下次触发,精度较差。

2. System.Timers.Timer 基于服务

--轻量级的计时器,每隔间隔时间,触发Elapsed事件,可加载成控件使用,也可以利用代码使用(System.Timers.Timer timer2 = new System.Timers.Timer()).

--应用:服务器,获取数据。

--局限:不可以修改UI元素,但可以通过UI元素this.invoke(action)调用委托修改UI元素。

--属性:timer2.interval =1000;timer2.AutoReset = false;//只会印发一次就停止了。

--事件: timer2.Elapsed += Timer_Elapsed;

--启动:timer2.start();

--停止:timer2.stop();

--优点:如果事件里单次执行了耗时的操作,不会使UI失去响应,不会影响下一次触发。

3. System.Threading.Timer 基于线程

--轻量级的计时器,每隔间隔时间,回调方法执行操作,可加载成控件使用,也可以利用代码使用。

--回调方法原型:public Timer(TimerCallback callback,object state,int dueTime,int period);

参数1(state):要使用信息的对象或者设为null;

参数2(dueTime):延迟启动的时间,单位ms;

参数3(period): 时间间隔,ms,period 时间间隔 设置为0或者-1,只会执行一次;Change方法可以让计时器重新启动。       

--demo

System.Threading.Timer timer3 = new System.Threading.Timer(new System.Threading.TimerCallback(o=>{      count2+=2;      Action<int> act = ShowCount;//定义委托      this.Invoke(act,count2);      }),null,0,1000);     private void ShowCount(int count)     {         txtCount.Text = count.ToString();     }

 --对线程池线程执行方法的机制,也就是基于多线程的,精度比较高。

--优点:如果事件里单次执行了耗时的操作,不会使UI失去响应,不会影响下一次触发。

--方法:timer3.Chang(2000,2000);//改变延迟启动时间和时间间隔。

--停止:timer3.Dispose();

--局限:不可以修改UI元素,但可以通过UI元素this.invoke(action)调用委托修改UI元素。 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易知道(ezd.cc)。

推荐阅读

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    stick和limb的区别?limb是 什么意思

    stick和limb的区别?limb是 什么意思,分词,枝干,本文目录stick和limb的区别limb是 什么意思shoot的过去式和过去分词limb英语是什么意思limb

    sticks and stones究竟是啥意思

    sticks and stones究竟是啥意思,动词,复数,本文目录sticks and stones究竟是啥意思sticks是什么意思sticks用英语怎么说stick是什么意思st

    cad怎么设置捕捉|cad怎么设置捕捉精度

    cad怎么设置捕捉|cad怎么设置捕捉精度,,1. cad怎么设置捕捉精度随意的画一条线,然后打开标注第一种方法:1、我们想要更改标注的精度,我们可以

    params 是什么意思,c#里

    params 是什么意思,c#里,参数,数组,本文目录params 是什么意思,c#里params.add跟params.put有区别吗C#中ref,out和params有什么区别发送请

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session,令牌,客户端,最近在研发一款O2O产品,考虑到分布式架构的需要,以前那一套.NET的

    c#中 (ToolStrip

    c#中 (ToolStrip,窗体,控件,本文目录c#中 (ToolStrip)控件是做什么用的winform窗体问题 toolstrip怎么重用,每个窗体都要用到同样的工具栏窗体

    C#取得DataTable最大值、最小值

    C#取得DataTable最大值、最小值,最大值,最小值,C#取得DataTable最大值、最小值int max=int.Parse((dtItemsAll.Compute("Max(CPITEMS_SOR

    300dpi怎么设置|精度300dpi怎么设置

    300dpi怎么设置|精度300dpi怎么设置,,精度300dpi怎么设置ps分辨率300dpi要设成“像素/英寸”的单位,因为dpi是指每英寸所含像素的数量。在p

    电脑十字绣精度|电脑机绣十字绣

    电脑十字绣精度|电脑机绣十字绣,,1. 电脑机绣十字绣你好!常规的电脑十字绣机器大概14万钱一台,也有小型的价格在6.5万左右。2. 电脑机绣十字