c# 的timer好奇怪哦 本帖最后由 kukumh 于 2009-08-25 09:21:44 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 应该是sleep之后wakeup的时候又重新执行一遍吧,不太清楚,等高手 这里 Thread.Sleep(200); 没把法把定时期休眠,只不过这个tmrShowData_Tick执行的时候休眠0.2秒 tmrShowData_Tick还是按照100的间隔继续执行 应该是 Thread.Sleep(200);这个问题 Thread.Sleep(200);只是把当前的线程暂停了,但是不会暂停Timer的执行。Timer仍是100后开始一个新的线程执行Tick事件。 不奇怪啊,你设置100毫秒触发一次的,而你一次执行响应中会等待200毫秒,所以在输出“2.”之前第二次执行被触发。Timer定时器是异步运行的,它的计时是在另一个线程中运行的,时间间隔一到,就委托主线程调用定时事件,而那些事件是委托主线程调用的,不是强制要执行的,所以是在主线程里排队执行,但遇到了Thread.Sleep(200);后,主线程空闲,第二次的定时事件就插班了,所以顺序就打乱了。 private void tmrShowData_Tick(object sender, EventArgs e) { Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Thread.Sleep(200);********************************************************************大哥,你的tmrShowData并没有停止计时呀,你的tmrShowData100毫秒执行一次,你一睡就睡了200ms,怎么能对呢?******************************************************************** Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Trace.WriteLine((x++).ToString()); } 是排队执行的,只要你的一次触发事件中没有任何停顿,就不会发生插班现象,而所有没来得及执行的触发事件将会进入Windows的消息队列排队,等待主线程空闲时执行。 1.35:156 //100个间隔 1.35:156 //100个间隔没有完成,有一个线程启动执行tick事件 2.35:359 // 0 2.35:359 //这个该如何解释? 0 很好,但是如果 我把 sleep换成一个较为复杂的函数,执行时间要超过100会怎么样? 建议楼主把timer 的 代码贴上来,才好分析 Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Trace.WriteLine((x++).ToString());你看了很不会分析别人的回复内容,我都说得很清楚了,你这里两句之间没有停顿,只要保证“一次触发事件中没有任何停顿,就不会发生插班现象”——我12楼的回复 private void tmrShowData_Tick(object sender, EventArgs e) { ShowCurves(); }其中ShowCurves()是一个较为复杂的函数,执行时间要超过100,我想知道这个时候tmrShowData_Tick的函数是怎么执行的 感觉: 1.35:156 1.35:156 //以上有Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);产生的 2.35:359 0 2.35:359 0 //由 Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Trace.WriteLine((x++).ToString());产生的但是为什么是双份呢? 这还不简单,你写个10万次循环,执行些简单的操作,比如乘法,但要注意到int最大值之前重新初始化下。循环次数增加,需要的时间就越长。自己看看会怎么样就知道了。 猜测 ShowCurves() 就是产生双份 的原因 private void tmrShowData_Tick(object sender, EventArgs e) { tmrShowData.Enabled = false; Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond); Trace.WriteLine((x++).ToString()); tmrShowData.Enabled = true; } 如果你的执行时间超过了Timer的间隔时间,而且这可能一直累积下去,我建议你不要设置那么短的间隔,不然你的CPU会一直100%运行中,程序本身甚至会无响应的。所以是否超过了Timer设置的间隔,看CPU使用率基本可以看得出来。 Timer都是异步计时,不过你可以设置Timer一次执行当中停止计时,调用“Timer.Stop();”把它停了,处理好任务后再调用“Timer.Start()”把它开启。当然要这么做的话,似乎使用System.Threading.Timer类操作好些,但是要注意System.Threading.Timer的事件触发执行也是异步的,而System.Windows.Forms.Timer的事件触发执行是已经调用过了委托的,是同步执行的。 出两次是不是双核的原因? 我为了不重入就加了 lock代码,但是出来了两次,是不是双核的原因。 我发现输出变乱的问题了,是trace的问题。不知道c#的trace是怎么回事。 c#的winform中的timer和c++的timer是一样的哦? 难道TRACE就是两份,真的好奇怪 不可能吧......我用楼主的代码,测试结果是:1.32:6092.34:62501.34:6252.36:62511.36:6252.38:6252....如果楼主真的用的是System.Windows.Forms.Timer,那么当前线程就是界面线程,Sleep了界面线程,消息循环当然也就停住了,System.Windows.Forms.Timer是用的消息循环,不可能有楼主这种输出。楼主这种输出很可能不是用的System.Windows.Forms.Timer。 对了,上面我把Sleep(200)改成Sleep(2000)了System.Windows.Forms.Timer的Tick是不会另起线程的,它是基于windows消息机制。 与双核当然没关系。从现象看,你的Timer事件是多个线程在执行,但System.Windows.Forms里的Timer是不会启动多线程的。 楼主方便的话把你的代码给我发一遍[email protected] 这里 Thread.Sleep(200); 没把法把定时期休眠,只不过这个tmrShowData_Tick执行的时候休眠0.2秒 tmrShowData_Tick还是按照100的间隔继续执行 C# 如何把二进制里的"1"变"0"把"0"换成"1"呢 c#文本框控件内容如何导入到word? C#发牌小程序有重复的问题,帮忙看看啦! winform打包时 插件怎么同时安装 两个关键字的互相查询的问题 如何让WINFORM的TREEVIEW的节点换行或者显示多行?(顶帖给分) .Net2005 连接数据库问题 DataGridView如何绑定外联类字段信息 C# 欢乐碰碰球 (需要.NET Framework1.1 4322以上支持) C#可以开发串口通讯程序吗? C# sql数据库中image数据类型问题 讨论一下,大家是用DIV还是用TABLE来控制布局?
tmrShowData_Tick还是按照100的间隔继续执行
只是把当前的线程暂停了,但是不会暂停Timer的执行。Timer仍是100后开始一个新的线程执行Tick事件。
Timer定时器是异步运行的,它的计时是在另一个线程中运行的,时间间隔一到,就委托主线程调用定时事件,而那些事件是委托主线程调用的,不是强制要执行的,所以是在主线程里排队执行,但遇到了Thread.Sleep(200);后,主线程空闲,第二次的定时事件就插班了,所以顺序就打乱了。
{
Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Thread.Sleep(200);
********************************************************************
大哥,你的tmrShowData并没有停止计时呀,你的tmrShowData100毫秒执行一次,你一睡就睡了200ms,
怎么能对呢?
********************************************************************
Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Trace.WriteLine((x++).ToString());
}
是排队执行的,只要你的一次触发事件中没有任何停顿,就不会发生插班现象,而所有没来得及执行的触发事件将会进入Windows的消息队列排队,等待主线程空闲时执行。
1.35:156 //100个间隔没有完成,有一个线程启动执行tick事件
2.35:359 //
0
2.35:359 //这个该如何解释?
0
Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Trace.WriteLine((x++).ToString());
你看了很不会分析别人的回复内容,我都说得很清楚了,你这里两句之间没有停顿,只要保证“一次触发事件中没有任何停顿,就不会发生插班现象”——我12楼的回复
{
ShowCurves();
}其中ShowCurves()是一个较为复杂的函数,执行时间要超过100,我想知道这个时候tmrShowData_Tick的函数是怎么执行的
1.35:156
1.35:156
//以上有Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);产生的 2.35:359
0
2.35:359
0
//由 Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Trace.WriteLine((x++).ToString());产生的但是为什么是双份呢?
这还不简单,你写个10万次循环,执行些简单的操作,比如乘法,但要注意到int最大值之前重新初始化下。循环次数增加,需要的时间就越长。自己看看会怎么样就知道了。
private void tmrShowData_Tick(object sender, EventArgs e)
{
tmrShowData.Enabled = false;
Trace.WriteLine("1." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Trace.WriteLine("2." + System.DateTime.Now.Second + ":" + System.DateTime.Now.Millisecond);
Trace.WriteLine((x++).ToString());
tmrShowData.Enabled = true;
}
我为了不重入就加了 lock代码,但是出来了两次,是不是双核的原因。
我用楼主的代码,测试结果是:
1.32:609
2.34:625
0
1.34:625
2.36:625
1
1.36:625
2.38:625
2
....
如果楼主真的用的是System.Windows.Forms.Timer,那么当前线程就是界面线程,Sleep了界面线程,消息循环当然也就停住了,System.Windows.Forms.Timer是用的消息循环,不可能有楼主这种输出。
楼主这种输出很可能不是用的System.Windows.Forms.Timer。
从现象看,你的Timer事件是多个线程在执行,但System.Windows.Forms里的Timer是不会启动多线程的。
tmrShowData_Tick还是按照100的间隔继续执行