kinsno 发表于 2014-11-30 11:11:58

C#如何实际25MS的精确定时

本帖最后由 kinsno 于 2014-11-30 11:22 编辑

需求描述:
我是一个C#的新手,学了大约一周,做了3个小软件,现在这是第3个小软件;
要用串口打开一个文本文件,然后一行一行的发送出去,发送的时间间隔固定为25ms;我发现使用使用C#自带定时器,根本达不到25MS;后来我自己从百度上折腾一些代码,发现都不是太符合我的需求;

1、自己写一个类的话,能否也能在类里面定义一个事件,这样就类似于使用官方定时器一样,也能模拟出一个中断效果;这样我使用自己的类定义一个变量,然后直接去中断内发送;
2、再开一个线程,然后读系统时间,然后比较,可是不晓得是我功力不到,还是根本不可行,10分钟下竟然有15秒的误差,这让我无法忍受;

有没有高手出来,帮忙指点一下;

现献上我自己没成型的代码;有人可以试一下,下载我的代码,然后使用我的文件来发送,准确的需求应该是:216975ms;应该是可以和系统时间对应得上的;
   


PS:我是个新手,还需要具体的案例我才能看明白的;好多时候,我经常知道要咋样干,就是不晓得应该用哪个类或压根不知道库里竟然有这个功能了;比如时间datatime,我还自己傻呼呼的上去把时间翻译成yy:mm:hh等格式;是否有高手愿意指点一下,在我的源代码上修改一二,或提供一个新的案例呢?
PS:不能影响主程序啊,这只是一个配套功能,所以不能让这个功能独占进程;我的进程是要干别的了;

谢谢;

nongxiaoming 发表于 2014-11-30 11:11:59

老哥,你没有看msdn的啊,这个timer是有多种的,默认winform那个是单线程timer,那个是没办法达到这个精度的。你没发现它和ui线程是用一个吗?也就是你在里面操作控件不会报跨线程操作异常。下面是msdn的说明:

25ms应该是没问题的,更高要求的可以用QueryPerformanceFrequency()和QueryPerformanceCounter(),这两个是win32 api的,需要封装一下。

funnynypd 发表于 2014-11-30 11:55:07

visual C++.

gwnpeter 发表于 2014-11-30 12:38:24

本帖最后由 gwnpeter 于 2014-11-30 12:44 编辑

不要用定时器控件,
定时器控件使用事件驱动,实时性比较差
使用多线程技术,使用 thread.sleep(),并且吧线程的优先级提高,这样会提高一点实时性能
如果还要更高的实时性,直接用系统 api 吧 度娘 CreateWaitableTimer

tangxh 发表于 2014-11-30 12:54:38

顶3楼

+1

tdh03z 发表于 2014-11-30 12:58:20

按楼上说的,用多线程中的sleep()实现,精度应该可以,要不用多媒体定时器,这个实际上也是多线程,不过用起来方便

系统带的定时器每秒只能中断16~18次,25ms精度肯定达不到。

我用C#的时间也不长,其实你如果以前用过VC或其他编程软件,有些可以相互借鉴的,C#写的程序在老电脑上CPU占用率高些,但学习容易,非常容易入门并编制自己需要的简单调试软件。

现在在用Delphi7写些CAN、串口调试软件,哈生成绿色软件,运行速度快,入门简单

uid81 发表于 2014-11-30 13:03:41

.net中有4中定时器,
System.Threading.Timer
System.Windows.Forms.Timer
System.Timers.Timer
System.Windows.Threading.DispatcherTimer
你肯定用的不对

gongxd 发表于 2014-11-30 13:26:14

多媒体定时器
RTX
实时扩展

NJ8888 发表于 2014-11-30 14:00:07

我觉得OS下保证精确定时不好办,虽然我用过queryperformancecounter一般可以但是权限有时会被系统剥夺

kinsno 发表于 2014-11-30 14:06:46

uid81 发表于 2014-11-30 13:03
.net中有4中定时器,
System.Threading.Timer
System.Windows.Forms.Timer


达不到这个精度,不信你可以试试,长时间运行,必然有误差;至少每小时不超过1S吧;要不就大了;

kinsno 发表于 2014-11-30 14:08:46

nongxiaoming 发表于 2014-11-30 13:16
老哥,你没有看msdn的啊,这个timer是有多种的,默认winform那个是单线程timer,那个是没办法达到这个精度 ...

兄弟,也忘了告诉你了,你那个程序在我电脑上不能运行的原因,估计你没有想到!就是缺少一个解码器,需要装一个解码器;

我也想用那个封装一下,我测试了一下,确实还可以哦,30分钟下来不超过1S,但是我不会封装啊,简单地说是我不会利用它封装成我想要的样子;不会耍啊;

kinsno 发表于 2014-11-30 14:12:31

NJ8888 发表于 2014-11-30 14:00
我觉得OS下保证精确定时不好办,虽然我用过queryperformancecounter一般可以但是权限有时会被系统剥夺 ...

是的,可是现在却需要这样一个功能,搞了2天了,周五周六两天了,一直没有好的结果,只好上坛子来悬赏了;

nongxiaoming 发表于 2014-11-30 14:18:08

kinsno 发表于 2014-11-30 14:08
兄弟,也忘了告诉你了,你那个程序在我电脑上不能运行的原因,估计你没有想到!就是缺少一个解码器,需要 ...

那个播放器的你把播放进度条换一下,我那里用的一个美化过的进度条,实际发现播放的时候更新进度条会有点卡顿,换成系统默认那种就没问题。

activeleo 发表于 2014-11-30 14:28:35

windows的系统调度时10Ms一次,你要25Ms定是本身就是不可能的任务 。。。。或者是PXI系统估计没问题!

ysu533 发表于 2014-11-30 15:30:27

本帖最后由 ysu533 于 2014-11-30 15:32 编辑

kinsno 发表于 2014-11-30 14:12
是的,可是现在却需要这样一个功能,搞了2天了,周五周六两天了,一直没有好的结果,只好上坛子来悬赏了 ...

25ms, 正常情况下是不可能满足的. 好像一个windows一个tick就是17ms(有一说是10-15ms), 9楼的方法不错. 可以尽可能的提高精度(要配合优先级, 最高优先级需要系统管理员身份), 但是25ms精确间隔, 真要这个指标是无解.
写过modbus的t3.5. 我发现即使间隔是17ms, 依然会连包. 但是18ms绝对不会(系统卡死另说).

要这个精确度, 请转战linux. 或者是自己在windows启动前加载自己的内核(据说西门子是这样的). 对楼主来说可能不太现实.

所以请楼主重新评估是否真需要这么高的精确度. 一般情况下是没有必要的. 如果真限死精确的25ms, 应该是无解的. 等同于单片机, 计数器跳一个数需要10-15ms, 你却要精确的定时25ms, 你觉得可能吗.

kinsno 发表于 2014-11-30 15:37:18

ysu533 发表于 2014-11-30 15:30
25ms, 正常情况下是不可能满足的. 好像一个windows一个tick就是17ms(有一说是10-15ms), 9楼的方法不错....

且再努力吧,明儿个上班了问问同事去;我觉得实际上应该是能达到的;不到最后,我还得努力努力啊;

ysu533 发表于 2014-11-30 15:45:31

kinsno 发表于 2014-11-30 15:37
且再努力吧,明儿个上班了问问同事去;我觉得实际上应该是能达到的;不到最后,我还得努力努力啊; ...

精确度我敢保证是100%达不到的. windows 本身就不是实时操作系统.但是你写软件(或者是设计)的思路应该是错的.

且不说windows本身的精确度. 另外windows也不是独占的, 你的程序还受别的程序的影响的.

windows在不加内核和驱动程序的情况下, 尽可能的提高精度的方式估计也就9楼的方式了.

ysu533 发表于 2014-11-30 15:48:18

NJ8888 发表于 2014-11-30 14:00
我觉得OS下保证精确定时不好办,虽然我用过queryperformancecounter一般可以但是权限有时会被系统剥夺 ...

好像不是说会被系统剥夺, 而是需要硬件支持. 我的程序就应到了. 目前没有碰到过不支持的机子.

kinsno 发表于 2014-11-30 15:56:52

ysu533 发表于 2014-11-30 15:45
精确度我敢保证是100%达不到的. windows 本身就不是实时操作系统.但是你写软件(或者是设计)的思路应该 ...

是需求就这个德性啊,需要25MS发一串数据出去;如果办不到,就要想办法偷鸡了;哈哈;
不过9楼说的那个办法,其实就是7楼小农提的那个,我在上面已经回答,现在已经实现了;
感觉不是太实用啊,我怕它独占CPU,我别的主程就不用干活了,所以且来找找有没有现优质的方法啊;

1、自己定义一个类 mytime,封装好;
2、在另外的FORM里面使用这个类 mytime time = new mytime xxxx
3、在同一个FORM里面,能这样子用不?
   private void timer_Tick(object sender, EventArgs e)
    {
          干活的;
    }

话说,自己写的类,有没有办法也模拟出一个事件啊,这样我就可以和官方自带库一样用定时器了;

superrf 发表于 2014-11-30 16:00:00

kinsno 发表于 2014-11-30 15:37
且再努力吧,明儿个上班了问问同事去;我觉得实际上应该是能达到的;不到最后,我还得努力努力啊; ...

首先,Windows操作系统不是实时操作系统,通常定时器精度15ms左右,Server版号称10~15ms。
由于你写的软件优先级问题,不是每个15毫秒CPU都会给分配时间的,也就是说部分15MS你的软件是不在运行。
如果你的软件刚醒过来,系统发现你的进程需要两个或定时器消息,系统会忽略只留1个,这样你的软件定时器就会少触发了。
还有C#是托管程序,软件运行的效率比原生程序差多了,微观上看,如遇到垃圾收集等系统行为时会影响软件触发时机。还C、C++效果会好些

给你一个解决思路,供参考
启动时记录开始时间,
当定时器触发时,记录定时器触发次数,同事获取系统时间,与开始时间比较,如果应该触发N次,而实际只触发了N-2次,那么在多执行两次软件逻辑(相当于软中断),
这样能保证定时器触发执行的逻辑次数是对的,需要注意的是获取时间的位数小心溢出,如GetTickCount,32位的到最大值后会掉头回来。
这种方法的问题是某个25毫秒会执行多次触发逻辑,触发的时间不准确,由于Windows是非实时操作系统这个无法完全避免。
为了提高定时器准确度,建议使用C或C++开发,最好写驱动。应用程序的优先级比较低,驱动优先级高些,而且C程序效率高些。

superrf 发表于 2014-11-30 16:01:37

这个解决办法简单点说就是把丢失的触发通过定时检查补回来

cjwdyzdd 发表于 2014-11-30 16:01:54

api GetTickCount(),但是系统其它进程和系统开销如果大于25ms,就会有延迟

kinsno 发表于 2014-11-30 16:02:35

superrf 发表于 2014-11-30 16:00
首先,Windows操作系统不是实时操作系统,通常定时器精度15ms左右,Server版号称10~15ms。
由于你写的软 ...

那岂不是要回头去折腾MFC,C++倒是不用管,MFC以前搞过一次,简直是噩梦,还是算了吧;伤不起;

superrf 发表于 2014-11-30 16:09:27

kinsno 发表于 2014-11-30 16:02
那岂不是要回头去折腾MFC,C++倒是不用管,MFC以前搞过一次,简直是噩梦,还是算了吧;伤不起; ...

每次定时器触发时,通过时间比对,如果发现丢失过定时器事件,可以多执行功能调用把触发次数补回来

superrf 发表于 2014-11-30 16:10:56

本帖最后由 superrf 于 2014-11-30 16:12 编辑

用C#就行,不需要换开发语言,换C只能减少丢失次数不能避免。定时器丢失根本原因是Windows不是实时操作系统.如果操作系统某些25ms没给你的进程分配时间片,定时器一点会丢失部分

ysu533 发表于 2014-11-30 16:11:28

kinsno 发表于 2014-11-30 15:56
是需求就这个德性啊,需要25MS发一串数据出去;如果办不到,就要想办法偷鸡了;哈哈;
不过9楼说的那个办 ...

好吧, 你相信能就能吧. 其实我也相信你能. 只是你的描述的有问题. 如果真能做到是精确到25ms发送一次(而不是24或者是26ms).

反正我在调试modbus的时候, 如果是单片机和pc通讯, 你别说间隔3.5ms发一个包, 就是10ms发一个包. 我发现我找到的modbus的调试软件还没有能解析出来的.

程序中只要一个sleep, 那么这个sleep具体多长时间根本不是一个可控的固定时间. 你不能就跑一个线程吧, 至少还有ui显示吧.

superrf 发表于 2014-11-30 16:16:21

当代码调用sleep(0)的时候会经历多长时间?大家知道吗

kinsno 发表于 2014-11-30 16:18:38

superrf 发表于 2014-11-30 16:09
每次定时器触发时,通过时间比对,如果发现丢失过定时器事件,可以多执行功能调用把触发次数补回来 ...

我理解你这个做法,关键问题是,如果定时器每次触发是100MS,那通过时间比对就没有意义了啊;

ysu533 发表于 2014-11-30 16:20:59

superrf 发表于 2014-11-30 16:00
首先,Windows操作系统不是实时操作系统,通常定时器精度15ms左右,Server版号称10~15ms。
由于你写的软 ...

其实楼主要实现的绝对没有那么复杂, 只是他描述的有问题. 如果他描述的没问题的话, 绝对是不可能实现的.

按楼主的需求既然要准确的25ms, 你找回丢失的定时器又有什么用呢. 找回定时器, 又不是时光倒流. 如果是要保证固定时间段内要发送完成多少次. 那又是另一种思路了.

楼主关键是很多需求没说明白. 比如, 有的包需要30ms才发出去, 这时会发生什么? 什么是可接受的, 什么是不可接收的? 一行数据长度是多少? 波特率又是多少? 25ms内是否能发送完一行数据这些考虑了吗?

superrf 发表于 2014-11-30 16:21:05

sleep(0)就是将交出当前进程CPU占用给系统,
1、如果系统空闲,系统会马上激昂CPU交给当前进程,可以认为Sleep了0毫秒
2、如果系统忙,系统会把时间片交给其他进程使用,下一个调度周期再交给当前进程时间。所以Sleep了0~15ms;
3、如果系统特别忙,而且当前进程优先级不高,下个调度周期也可能之后N个调度周期后才给当前进程分配时间片,那么Sleep了多久是未知数,可能大于25ms或更多

kinsno 发表于 2014-11-30 16:21:33

ysu533 发表于 2014-11-30 16:11
好吧, 你相信能就能吧. 其实我也相信你能. 只是你的描述的有问题. 如果真能做到是精确到25ms发送一次(而 ...

我真正的需求是两方面,
1、正在播放视频
2、每隔25MS发一个数据出去,管发不管收;但是要尽量准啊,因为需求是25MS精确,如果偷鸡的话,24或26也可以啊,总不能跑到50MS一次就差远了啊;
3、所以我的主进程实际上就是库里那个播放视频的软件函数,本来打算在定时中断内发送数据,每25MS进来一次,后来才发现,差远了,拿示波器一根,简直了;

superrf 发表于 2014-11-30 16:24:28

定时器的原理是,系统根据进程登记的定时器信息,在每个调度周期计算是否需要给进程发送定时器消息,如果需要发送定时器消息,则将定时器消息插入到当前进程消息队列。当前进程在消息循环中获取定时消息并触发事件。
如果操作系统在某个调度周期需要给当前进程时间片的时候,发现需要2个定时器消息,那么系统只会给当前进程消息队列插一个,另一个会被丢弃

superrf 发表于 2014-11-30 16:27:03

kinsno 发表于 2014-11-30 16:18
我理解你这个做法,关键问题是,如果定时器每次触发是100MS,那通过时间比对就没有意义了啊; ...

通常25毫秒会触发一次的,丢失是小概率事件。如果系统特别忙,触发时间会延长,但是通常系统不会一直忙的。
如果系统CPU一直满负荷运行的话,系统跟死机差不多,整个反应缓慢,鼠标键盘都不响应,相信大家遇到过这样的情况

ysu533 发表于 2014-11-30 16:29:07

kinsno 发表于 2014-11-30 16:21
我真正的需求是两方面,
1、正在播放视频
2、每隔25MS发一个数据出去,管发不管收;但是要尽量准啊,因为 ...

偷鸡是什么意思? 关键是你要说明白25ms一包, 发生50ms才发出去会怎么样, 会发生多严重的事? 可不可接受? 就windows平台, 你别说50ms才发出去, 很多极端情况下1分钟你都未必能发出去(而且你不能事先知道发不出去, 而进行补救).

如果真这么严格, 外接个单片机板吧, 交给他干. 反正这里主要都是搞电子的.

superrf 发表于 2014-11-30 16:29:44

kinsno 发表于 2014-11-30 16:21
我真正的需求是两方面,
1、正在播放视频
2、每隔25MS发一个数据出去,管发不管收;但是要尽量准啊,因为 ...

这种需求应该用实时操作系统解决,Windows不适合干这个
如果用单片机,ARM等实现25ms太轻松了,如果FPGA,25微秒都没问题
如果非要用Windows,最好写到驱动里。

superrf 发表于 2014-11-30 16:30:59

如果不写驱动,那么用C/C++的语言写程序准确度会高些

superrf 发表于 2014-11-30 16:31:49

如果只能用C#,还有一个办法,那就是写成系统服务,这样进程的优先级会高些,定时器会更准确些

farmerzhangdl 发表于 2014-11-30 16:36:09

如果是windows下实现,建议不用努力了,在windows下最精确的定时器也不过在50ms左右,用API也没用,究其原因是因为windows本身不是一个抢占时的实时系统。
另外还有个原因是C#本身是虚拟机的机制,系统会时不时的做垃圾收集,在收集的时候必然会延缓你的程序动作。

superrf 发表于 2014-11-30 16:41:09

windows下实现25ms触发,无论任何方案都解决不了不能准确的问题,因为操作系统的问题。各种办法只能提高触发的准确度,减少丢失的几率。
如提高软件执行速度,用C、C++
提高软件运行优先级,将将程序写成系统服务,或者写到驱动层

nongxiaoming 发表于 2014-11-30 16:41:30

ysu533 发表于 2014-11-30 16:11
好吧, 你相信能就能吧. 其实我也相信你能. 只是你的描述的有问题. 如果真能做到是精确到25ms发送一次(而 ...

如果是精准的到25ms的话肯定做不到啊,这个又不是硬件timer,软件timer是以系统的tick做基准的,windows根本搞不来精度到这个的。我说觉得楼主是不是想一直跑这个误差不会一直累加的问题。比如这一次间隔是24ms,下一次间隔是26ms,是一个总体互补的关系。而不是跑个个把小时这个就偏差几百秒那种。应该是每一次是独立的误差,即使跑个个把小时,误差也会在这个范围不变。也就是并不要求每一次都很均匀的25ms那种。对于软件定时器来说,这样太难了。除非tick基准是1ms的或5ms的,这样才有可能是25ms准确。

ysu533 发表于 2014-11-30 16:44:17

superrf 发表于 2014-11-30 16:31
如果只能用C#,还有一个办法,那就是写成系统服务,这样进程的优先级会高些,定时器会更准确些 ...

后台服务是否比前台优先级高, 取决于pc设置, 见[高级系统设置]里面[性能]选项卡设置(一般默认非服务器版本, 前台程序优先级高, 服务器版本服务程序优先级高).

但是可以调用api来提升优先级. 但是在win7下(更高版本没测试过), 非管理员模式运行最高优先级实际只能到15(好像是, 15还是16, 最高好像是31, 具体参考api说明), 管理员模式下运行能提到30还是31(最高或者是最高减1, 忘了).

用9楼的性能计数器+高优先级, 能提高精度. 但是和楼主要的精度还是有区别. 其实楼主也没说精度, 只是说要精确的25ms发一次. 没说允许的精确度

nongxiaoming 发表于 2014-11-30 16:59:34

ysu533 发表于 2014-11-30 16:44
后台服务是否比前台优先级高, 取决于pc设置, 见[高级系统设置]里面[性能]选项卡设置(一般默认非服务器版 ...

windows的tick默认是64的,也就是15.625ms一个tick。或许楼主可以学学chrome,把tick改成1000或200,这样精度就上去了。

yigang 发表于 2014-11-30 17:26:00

本帖最后由 yigang 于 2014-11-30 17:39 编辑

抢占式系统,真的不想吗?有些程序(软件)肯定是有高精度时间要求的吧?

这个问题很有挑战啊!

40楼的分析更准确。。。

很多年前,在打印机并口上搞过一个项目,也是用示波器看25MS时间在抖动,后来加了“外时钟元”有改善,但是做不好。
建议:用 TICK 配合外部电路。 因为 TICK 是15.XMS. 小于25MS。 15.X + 15.X< 50MS(2次25MS)。

nongxiaoming 发表于 2014-11-30 17:28:01

superrf 发表于 2014-11-30 16:41
windows下实现25ms触发,无论任何方案都解决不了不能准确的问题,因为操作系统的问题。各种办法只能提高触 ...

这个软件timer的基准问题,还语言关系不大。系统给的默认基准是15.6ms,你用啥语言,只要是软件timer,就逃脱不了这个。就比如我给你最小刻度为15cm的尺子,不能累加做平均,你要给我准确的量出25cm,怎么量?要想更加精确就修改这个基准,或找其他更好的基准。

nongxiaoming 发表于 2014-11-30 17:33:08

可以看这个帖子,http://stackoverflow.com/questions/23215970/system-threading-timer-vs-system-threading-thread-sleep-resolution-net-timer
里面精度是上去了,但看方法应该比较耗cpu。

yigang 发表于 2014-11-30 17:59:28

本帖最后由 yigang 于 2014-11-30 18:10 编辑

端口控制在WINDOWS里也分层,会受系统上层调度影响,所以外部电路配合方法不可取。。。
见笑了。。。

kinsno 发表于 2014-11-30 18:04:18

nongxiaoming 发表于 2014-11-30 17:33
可以看这个帖子,http://stackoverflow.com/questions/23215970/system-threading-timer-vs-system-threadi ...

小农,看着了,一会来研究;

其实我这个功能是配合视频来动作的,每隔25MS就要发1组数据出去;确实如你上楼所说,是总体不要有误差;我现在是视频放完了,数据没发完或提前发完了;所以想看看能不能精确地控制25MS;
我想告诉你的是,有人已经实现这个功能了,我只是想重现这个软件罢了;

yigang 发表于 2014-11-30 18:13:23

本帖最后由 yigang 于 2014-11-30 18:15 编辑

kinsno 发表于 2014-11-30 18:04
小农,看着了,一会来研究;

其实我这个功能是配合视频来动作的,每隔25MS就要发1组数据出去;确实如你 ...

掺合一下,数据发往哪里?

ysu533 发表于 2014-11-30 18:37:58

kinsno 发表于 2014-11-30 18:04
小农,看着了,一会来研究;

其实我这个功能是配合视频来动作的,每隔25MS就要发1组数据出去;确实如你 ...

如果是配合视频的话就太简单了,和定时器精度无关,只要和视频步调一致,这是两个概念。

kinsno 发表于 2014-11-30 18:40:50

ysu533 发表于 2014-11-30 18:37
如果是配合视频的话就太简单了,和定时器精度无关,只要和视频步调一致,这是两个概念。 ...

说白点某种意义上和电影的字幕或者音乐的歌词同步是一个意思;
晕,那也得25MS发一次数据啊;
请教一下,如何和视频一致,因为我的数据是正好25MS发一次,正好发到最后数据发完,视频放完;

ysu533 发表于 2014-11-30 18:40:58

kinsno 发表于 2014-11-30 18:04
小农,看着了,一会来研究;

其实我这个功能是配合视频来动作的,每隔25MS就要发1组数据出去;确实如你 ...

你要说有人实现了,是指和视频同步发送完?还是用示波器测试他能规律的控制在25ms。如果是后者可以的话上图让大家见识下吧

kinsno 发表于 2014-11-30 18:43:37

ysu533 发表于 2014-11-30 18:40
你要说有人实现了,是指和视频同步发送完?还是用示波器测试他能规律的控制在25ms。如果是后者可以的话上 ...

我用的时候没有示波器,因为我用25MS中断定时收的,基本上控制在25MS左右;
我在下位机用串口打印出来的;基本上只有少许是在24MS,绝绝大部分在25MS发下来的数据;

kinsno 发表于 2014-11-30 18:44:07

yigang 发表于 2014-11-30 18:13
掺合一下,数据发往哪里?

发给下位机的,相当于配字幕;

ysu533 发表于 2014-11-30 18:47:24

kinsno 发表于 2014-11-30 18:40
说白点某种意义上和电影的字幕或者音乐的歌词同步是一个意思;
晕,那也得25MS发一次数据啊;
请教一下, ...

你找个开源的播放器看看吧,不是这么同步的。你看视频应该也有注意有时候系统卡住,视频恢复播放会有快进一样的效果

armstrong 发表于 2014-11-30 20:46:51

无论windows还是linux,要实现真的实时,得从驱动程序入手。

小柯师傅 发表于 2014-11-30 23:43:34

不能从视频流中得到 帧间隔*(当前桢-起始桢)不是就可以同步了么?要绝对精确的时基有什么特别目的?

kinsno 发表于 2014-12-1 08:30:49

小柯师傅 发表于 2014-11-30 23:43
不能从视频流中得到 帧间隔*(当前桢-起始桢)不是就可以同步了么?要绝对精确的时基有什么特别目的? ...

数据文件的大小(每25MS发一次的话,它的帧数)正好和AVI视频时间长度是一样的; 所以我打算25MS发送一次;


你说的方法可以,可是我不会弄啊,所以我想出来了另外一个招,就是用一个绝对正确的定时器来配合干活,和AVI视频同步开启;

embeddev_1 发表于 2014-12-1 08:38:48

关注一下~{:biggrin:}

sunjianmax232 发表于 2014-12-1 08:41:09

个人觉得.net不太适合做这种精确控制的应用,它经过.net框架的封装,最后才来调用最底层api,还要再加上它的一些回收机制。用vc++6.0试试吧,这个应该实时性好的多。

gwnpeter 发表于 2014-12-1 10:07:19

本帖最后由 gwnpeter 于 2014-12-1 10:27 编辑

如果是配合视频的,那么楼主就是思路有问题了。
    就像有人向我抱怨说液晶屏怎么这么慢,完全不够使用,了解了一下,原来是进行ad采集,每次采集一个数据,就向液晶写入一次..........我倒.......能不慢吗
所以,向下位机发送字幕数据,200ms一次都可以了,我不相信有人能一秒看5行字幕。
应该使用200ms定时器,然后判断现在的时间,决定应该发出哪行字幕到下位机....这样没有累计错误
如果你用25ms的定时器,如果有0.1%的误差,那么一个小时就会有3.6s的误差,这个字幕和声音的配合,这个才会让人抓狂............
而0.1%的误差已经是很高的精度了......................................................................!!!!!!!!!

楼主一开始的楼就歪了.........别人在后面就只能限制在思维的定势里面了.........
方向不对,努力会白费..哈哈

kinsno 发表于 2014-12-1 10:21:13

gwnpeter 发表于 2014-12-1 10:07
如果是配合视频的,那么楼主就是思路有问题了。
    就像有人向我抱怨说液晶屏怎么这么慢,完全不够使用, ...

我理解你的意思;

哎,一开始我也说了,原来我使用人家的软件调的,可是别人软件确实就是25MS给我一个数据,我特地的用串口跟踪过啊;

看来我的问题只能搁浅了,别人的软件无法借鉴了,今儿再试验一天,解决不了就放弃了,另想一条别的法子了;

gwnpeter 发表于 2014-12-1 10:26:48

kinsno 发表于 2014-12-1 10:21
我理解你的意思;

哎,一开始我也说了,原来我使用人家的软件调的,可是别人软件确实就是25MS给我一个数 ...

再退一步,及时是使用25ms的定时器,也要通过判断 现在的时间 ,决定应该发出哪行字幕到下位机....这样没有累计误差,也不会受到25ms的定时器的精度影响,这个才是正道

god-father 发表于 2014-12-1 10:27:43

我通过TIMER控件在VC上实现定时非常方便,误差问题倒是没注意。

kinsno 发表于 2014-12-1 10:29:35

god-father 发表于 2014-12-1 10:27
我通过TIMER控件在VC上实现定时非常方便,误差问题倒是没注意。

控件嘛都是可以用的,但是一般我们都不会用在这种短时内的计时上面的啊;一般我们的程序起码是100MS以上的延迟为数嘛;所以不会有这种问题的;

kinsno 发表于 2014-12-1 10:32:28

本帖最后由 kinsno 于 2014-12-1 10:34 编辑

gwnpeter 发表于 2014-12-1 10:26
再退一步,及时是使用25ms的定时器,也要通过判断 现在的时间 ,决定应该发出哪行字幕到下位机....这样没 ...

比如我有10000条数据,25MS发一次,正好发完10000次,正好视频长度大小一模一样;这样视频主完,我数据发完;不存在你那个问题,我是必须要完发,要和视频同步的;漏一条都不行的;
PS : 或许你会问题,字幕有必要这样高精度吗?我发的不一定是字幕,只是打个比喻而已;核心就是既要同视频同步,又要把数据发完;
PS :视频是别人提供的,数据也是别人提供的,正好是按视频长度除以25MS一对一的;

gwnpeter 发表于 2014-12-1 10:32:51

本帖最后由 gwnpeter 于 2014-12-1 10:40 编辑

kinsno 发表于 2014-12-1 10:21
我理解你的意思;

哎,一开始我也说了,原来我使用人家的软件调的,可是别人软件确实就是25MS给我一个数 ...

---> 再开一个线程,然后读系统时间,然后比较,可是不晓得是我功力不到,还是根本不可行,10分钟下竟然有15秒的误差,这让我无法忍受
这个思路也是不对的,不是比较时间,而是根据系统时间,算出应该发哪行数据,如果需要你说的必须发出所有行的数据或者类似的东西,
那么你使用5ms的定时器(甚至可以使用applaction.doevent(),或者thread.sleep(0)),然后根据系统时间,算出应该发哪行数据,并且判断这个数据是否已经处理了....

kinsno 发表于 2014-12-1 10:35:53

gwnpeter 发表于 2014-12-1 10:32
---> 再开一个线程,然后读系统时间,然后比较,可是不晓得是我功力不到,还是根本不可行,10分钟下竟然 ...

关键是我不知道咋样在25MS去和系统时间配合啊,只好想出这么一个歪招拉;

569350810 发表于 2014-12-1 10:52:45

解答的不错,层层深入,步步逼近。。
终于知道了楼主想干嘛{:lol:}

ysoni 发表于 2014-12-1 10:57:33

kinsno 发表于 2014-12-1 10:21
我理解你的意思;

哎,一开始我也说了,原来我使用人家的软件调的,可是别人软件确实就是25MS给我一个数 ...

别人的软件也发上来看看

gwnpeter 发表于 2014-12-1 11:05:57

本帖最后由 gwnpeter 于 2014-12-1 11:28 编辑

        void thread_run()
        {
                DateTime ot = Now();
                TimeSpan ts;
                int t1;
                int t2;
                do {
                        ts = Now() - ot;
                        t1 = (int)ts.TotalMilliseconds;
                        t1 = t1 / 25;
                        if (t1 != t2) {
                                t2 = t1;
                                Console.WriteLine("line:" + t1.ToString + " at " + ts.TotalMilliseconds.ToString);
                        }
                        Threading.Thread.Sleep(1);
                } while (true);
        }



line:137 at 3413.1952
line:138 at 3438.1966
line:139 at 3463.198
line:140 at 3488.1995
line:141 at 3513.2009
line:142 at 3538.2023
line:143 at 3563.2038
line:144 at 3588.2052
line:145 at 3613.2066
line:146 at 3638.2081
line:147 at 3663.2095
line:148 at 3688.2109
line:149 at 3713.2123
line:150 at 3738.2138
line:151 at 3763.2152
line:152 at 3788.2166
line:153 at 3813.2181
line:154 at 3838.2195
line:155 at 3863.2209
line:156 at 3893.2226
line:157 at 3913.2238
line:158 at 3938.2252
line:159 at 3963.2266
line:160 at 3988.2281

god-father 发表于 2014-12-1 11:17:19

kinsno 发表于 2014-12-1 10:29
控件嘛都是可以用的,但是一般我们都不会用在这种短时内的计时上面的啊;一般我们的程序起码是100MS以上 ...

我用TIMER控件做串口通讯的间隔发送,是几十个毫秒都可以的。

gwnpeter 发表于 2014-12-1 11:22:24

gwnpeter 发表于 2014-12-1 11:05
void Main()
        {
                DateTime ot = Now();


楼主需要的不是没有误差,而是消除累计误差,我这段程序可以将累计误差控制在1ms以内

kinsno 发表于 2014-12-1 13:50:38

gwnpeter 发表于 2014-12-1 11:22
楼主需要的不是没有误差,而是消除累计误差,我这段程序可以将累计误差控制在1ms以内 ...

我表示不理解的是,你有一个SLEEP啊,这样能基本均称地控制在25MS左右吗?SLEEP有时候会差去大几十毫秒啊;

kinsno 发表于 2014-12-1 13:53:55

gwnpeter 发表于 2014-12-1 11:05
void thread_run()
        {
                DateTime ot = Now();


请教:
你这个单位是MS还是秒啊?
你这个用法是不是要在主程之外再开一个线程,这个线程就是 thread_run?

gwnpeter 发表于 2014-12-2 01:57:24

kinsno 发表于 2014-12-1 13:53
请教:
你这个单位是MS还是秒啊?
你这个用法是不是要在主程之外再开一个线程,这个线程就是 thread_run ...

t1 = (int)ts.TotalMilliseconds
        ----------当然是ms了

thread_run
        这个是另外一个线程里面的程序,目的是避免主线程被阻塞


sleep是避免大量占用cpu的,sleep(1)是延时1ms,但是因为这个函数的不准确性,实际是会一点差别的,但是在系统负荷不大的情况下,不会有严重的偏差
另外,可以提升process 的优先级,以及提升 thread的优先级,来达到比较准确的效果


line:137 at 3413.1952
line:138 at 3438.1966
line:139 at 3463.198
line:140 at 3488.1995
line:141 at 3513.2009
line:142 at 3538.2023
line:143 at 3563.2038
line:144 at 3588.2052
line:145 at 3613.2066
line:146 at 3638.2081
line:147 at 3663.2095
line:148 at 3688.2109
line:149 at 3713.2123
line:150 at 3738.2138
line:151 at 3763.2152
line:152 at 3788.2166
line:153 at 3813.2181
line:154 at 3838.2195
line:155 at 3863.2209

这个结果说明产生的25ms的间隔还是比较准确的,有些误差也无所谓,主要是没有累计误差...........就不会产生不同步的想象

nongxiaoming 发表于 2014-12-2 02:58:57

你这个是要发字幕?发字幕就不需要这么来搞啊,会搞死人的。25ms发一次,每秒40帧啊,完全就没意义了,一秒钟哪里会有40条字幕去?你发字幕应该有字幕文件啊,想办法把里面的时间轴解析出来,按时间轴去发就好了,但这样发送到下面再显示可能有点滞后,补偿一下应该就好了。而且播放媒体文件提供的IMediaPosition接口里就有CurrentPosition属性,这个是当前播放到的时间,double类型的,很准确的,当然这个要看你的视频帧数,但总你直接去轮询这个都比你搞个timer 要准呀。

huangqi412 发表于 2014-12-2 08:07:30

多媒体定时器加cpu时钟计数器搞定 多媒体定时器偶尔有跳动应该在可接受范围 通过时钟计数器解决累积误差电脑卡问题不考虑 电脑卡了神仙也不能反科学 加高配置,不干别的事就好

huangqi412 发表于 2014-12-2 08:17:18

如果发送数据非实时生成(传感器才是,比如摄像头麦克风)其实楼主问题纯钻牛角尖 电脑应该每1秒发一大批数据 在下位机做精准25毫秒定时将收到的大批数据裁剪成使用 再考虑隔段时间同步时间啊收发应答啊稳定性问题电脑适合干大任务 单片机适合干频繁微任务

朝闻夕道 发表于 2014-12-2 08:19:21

路过,MARK;

huangqi412 发表于 2014-12-2 08:20:12

从楼主描述是文本文件数据不是实时生成 那干嘛25一次 不是脑子进水啊么

kinsno 发表于 2014-12-2 08:25:09

nongxiaoming 发表于 2014-12-2 02:58
你这个是要发字幕?发字幕就不需要这么来搞啊,会搞死人的。25ms发一次,每秒40帧啊,完全就没意义了,一秒 ...

我倒,小农看贴不仔细;   我举字幕只是打个比方,并不是实际上的发字幕,而是类似于字幕一样的功能,因为数据源的长度和视频长度一致的,只有根据25MS发一包数据,才可以在视频长度发完的时候,数据源正好发完,构成一个同步效果,否则要么数据源发完,视频却没播放完,要不就是视频播放完数据源却没发完;

我找不到合适的办法,所以才要找精确的25MS;

huangqi412 发表于 2014-12-2 08:26:11

如果你是观众 给你一双时间分辨率1ms钛金眼 你能看出电脑一步到位25毫秒发包 和电脑一秒打包单片机再25毫秒二次发包的区别??

kinsno 发表于 2014-12-2 08:26:45

huangqi412 发表于 2014-12-2 08:20
从楼主描述是文本文件数据不是实时生成 那干嘛25一次 不是脑子进水啊么

你说对了,不是实时生成的,是提前制作好的,就是25MS一次的数据,比如视频有多长,它就是根据这个多长时间除以25MS,然后每个25MS发一包数据,把这些数据整合成一个数据源;   我就是要让这视频播放的同时发送数据源,让它两正好同步完成;
脑子进水,好象是有点啊;不晓得是谁制订的这个规则,真心蛋疼啊;

kinsno 发表于 2014-12-2 08:27:55

huangqi412 发表于 2014-12-2 08:26
如果你是观众 给你一双时间分辨率1ms钛金眼 你能看出电脑一步到位25毫秒发包 和电脑一秒打包单片机再25毫秒 ...

都说了不是字幕啊,兄弟,我倒; 你看上楼,我给小农的回答,你就明白了,我只是拿字幕打一个比方罢了; 我们人眼看不出25MS,但是机器能识别啊;下位机能识别啊,我上位机只要负责发出去,也不要应答,人家收不收得到,不关我的事;

kinsno 发表于 2014-12-2 08:29:04

gwnpeter 发表于 2014-12-2 01:57
t1 = (int)ts.TotalMilliseconds
        ----------当然是ms了



请教:
       为啥我在XP上面使用这段代码,打印出来的误差基本在31-32左右呢?百思不得其解啊;
      

huangqi412 发表于 2014-12-2 08:38:44

kinsno 发表于 2014-12-2 08:26
你说对了,不是实时生成的,是提前制作好的,就是25MS一次的数据,比如视频有多长,它就是根据这个多长时间除 ...

电脑分解成一秒数据单片机再次分解 变成25ms数据妥妥的只要你单片机时间和内存没榨干就行 不加一分钱成本上位机写的多烂都不怕

huangqi412 发表于 2014-12-2 08:43:22

kinsno 发表于 2014-12-2 08:27
都说了不是字幕啊,兄弟,我倒; 你看上楼,我给小农的回答,你就明白了,我只是拿字幕打一个比方罢了; 我们人 ...

我知道不是字幕啊上面我一直说的是数据字幕字幕的念那是外行人   电工只认数据 只分析数据性质 不管数据内容是苍老师声音还是木子美文字
没叫我上面在说的是你的数据非实时生成啊

kinsno 发表于 2014-12-2 08:43:25

huangqi412 发表于 2014-12-2 08:38
电脑分解成一秒数据单片机再次分解 变成25ms数据妥妥的只要你单片机时间和内存没榨干就行 不加一分 ...

先搞搞25MS,反正电脑不干别的事,把别人电脑搞死了也不关我事,哈哈;实在不行了,再弄个下位机来转发,那是不得已的下策了啦;

star_tale 发表于 2014-12-2 08:50:42

我也再整,三楼说出了真相,我请教过高手了,也说用现成延时

huangqi412 发表于 2014-12-2 08:52:12

kinsno 发表于 2014-12-2 08:43
先搞搞25MS,反正电脑不干别的事,把别人电脑搞死了也不关我事,哈哈;实在不行了,再弄个下位机来转发, ...

你还在钻牛角尖如果是批量产品坐等你死的难看客户电脑千差万别 有人机子老有人机子四核有人系统ghost有人一堆病毒,人家不管原因就一句话为毛你的程序不准啊?就算是单台定制,电脑BC足够把电脑搞慢打败你把电脑软件容忍度尽量提高才无惧电脑BC和垃圾电脑 他们搞不坏你的单片机程序兼容和时间要求严的放单片机

kinsno 发表于 2014-12-2 08:54:35

huangqi412 发表于 2014-12-2 08:52
你还在钻牛角尖如果是批量产品坐等你死的难看客户电脑千差万别 有人机子老有人机子四核有人系统ghost ...

我晕?好吧,钻牛角尖了;这不是我的需求,如果是我来搞,我不会搞成这样子了;
不过你说的很对,各式各样的人和电脑;

dongdaxing 发表于 2014-12-2 08:54:37

操作系统里面的精确定时 好像不大可能

kinsno 发表于 2014-12-2 08:55:41

请教 : 作第二手准备,弄一个下位机板子,我打算搞成100MS定时,为啥C#自带的定时器做100MS,也不太准呢?我就奇了怪了;总是比电脑时间距的慢几秒;

gwnpeter 发表于 2014-12-2 09:17:40

你用下位机搞转发,还是要用我那个好点,或者改成20ms

gwnpeter 发表于 2014-12-2 09:19:30

的定时器,因为rtc系统和cpu不是同一个时钟,有偏差的

gwnpeter 发表于 2014-12-2 09:21:16

你用下位机搞转发,还是要用我那个好点,或者改成20ms的定时器,因为rtc系统和cpu不是同一个时钟,有偏差的。晕,手机发帖,怎么就成了付费主题…

huangqi412 发表于 2014-12-2 09:42:34

倒 下位机不是你做的啊 那就没法不加成本了

kinsno 发表于 2014-12-2 09:58:07

gwnpeter 发表于 2014-12-2 09:21
你用下位机搞转发,还是要用我那个好点,或者改成20ms的定时器,因为rtc系统和cpu不是同一个时钟,有偏差的 ...

用你那个,关键是我不晓得把把串口发送放在哪个地方啊,是不是放在我上面所说的那个地方啊?那样子的话,感觉灵活度不高啊;

kinsno 发表于 2014-12-2 09:59:01

huangqi412 发表于 2014-12-2 09:42
倒 下位机不是你做的啊 那就没法不加成本了

不是啊,下位机和我无关,但我以前用下位机侦测过,上位机和我有关系;

huangqi412 发表于 2014-12-2 10:14:41

kinsno 发表于 2014-12-2 09:59
不是啊,下位机和我无关,但我以前用下位机侦测过,上位机和我有关系; ...

电脑精确定时这事挑电脑挑客户 加几块钱转发靠谱
页: [1] 2
查看完整版本: C#如何实际25MS的精确定时