搜索
bottom↓
回复: 16

C#定时器阻塞操作导致定时器多次被调用?导致无数弹窗!

[复制链接]

出590入992汤圆

发表于 2020-6-24 16:24:47 | 显示全部楼层 |阅读模式
RT。
之前一直没有注意过。
简化问题后:具体是这样:
一个定时器:周期100ms进入。如果这100ms定时器里面的任务没有处理完。发现:它好像会再调用一次副本,重新开始执行!于是不断的循环执行!这个完全违背我设计的想法。

请教:这是什么原理?应该如何解决(现在我的方法是:进入定时器后关闭定时器,处理完任务后再启用定时器!)
但是重点:我想知道其中的机制是什么,为什么是这样操作。(我做单片机比较多,一般如果单片机定时器一个中断没有处理完,程序还是留在中断函数中循环操作。)

于是我重新写了个展示程序:定时器里面用:MessageBox.Show()来阻断定时器完成。
代码如下:
  1.         int i = 0;
  2.         private void timer1_Tick(object sender, EventArgs e)
  3.         {
  4.             if (i == 0)
  5.             {
  6.                 DialogResult dr = MessageBox.Show("好多弹窗,是否强制退出?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Hand);
  7.                 if (dr == DialogResult.OK)
  8.                 {
  9.                     this.Dispose();
  10.                     this.Close();
  11.                 }
  12.                 i++;
  13.             }
  14.         }

  15.         private void button1_Click(object sender, EventArgs e)
  16.         {
  17.             timer1.Enabled = true;
  18.         }
复制代码


实测效果:


代码附件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2020-6-24 16:40:25 | 显示全部楼层
其实在定时器所触发的函数半天执行不完,和中断服务函数中的代码半天执行不完一样,都是不太正常的
这块感觉首先应该考虑换一个处理的方式

出0入0汤圆

发表于 2020-6-24 16:45:50 | 显示全部楼层
如果期望的效果是每次执行完之后多长时间再执行下一次,那基本上不管是改 Enabled, 还是 Start(), Stop(), 或者还有类似 timer.Change(1000, Timeout.Infinite) 这样的方法,都是在回调函数中修改了 timer

写过 JavaScript 的话,应该比较好接受这一点,JS 中经常会在 setTimeout() 所指定的回调函数末尾再执行 setTimeout() 来设置下一次 timeout
用 setInterval() 的机会反倒少一些

出0入0汤圆

发表于 2020-6-24 17:21:07 | 显示全部楼层
可能是这样: timer 计数到100ms 然后 开启新线程调用你的处理函数,然后再次计数  再次到100ms 然后又开启线程。 没研究过。 你可以在你的处理函数里面看看当前线程ID

出0入442汤圆

发表于 2020-6-24 17:21:53 来自手机 | 显示全部楼层
定时器可能是win内核创建的线程做的回调,因此要想取消你可以写个线程,每100ms调一下接口,这样就是阻塞的。

出0入0汤圆

发表于 2020-6-24 19:22:59 | 显示全部楼层
if 是否已执行 = false then
   是否已执行 = true
''''长时间的操作程序动作

是否已执行 = false
end if

出40入42汤圆

发表于 2020-6-24 19:27:36 来自手机 | 显示全部楼层
定时器里面最后不要有弹窗,一定要弹窗的话也应该做好保护,好像是定时器消息在调用界面阻塞线程后,系统会另外开辟定时消息响应

出300入477汤圆

发表于 2020-6-24 19:33:56 来自手机 | 显示全部楼层
落叶知秋 发表于 2020-6-24 19:27
定时器里面最后不要有弹窗,一定要弹窗的话也应该做好保护,好像是定时器消息在调用界面阻塞线程后,系统会 ...

定时器里弹窗,弹岀的窗口里面还是有消息循环的,那个消息循环仍然可以收系统发来的timer消息。做windows编程的人应该很熟悉次种行为啊。
常见的解决方法就是,进了timer就关掉这个timer。想继续定时触发它,就在退岀处理函数之前重新打开。
不必担心这样导致定时不准。你要在这里面弹窗,原本就已经不可能准时了。弹
窗函数什么时候返回取决于用户什么时候点它。

出300入477汤圆

发表于 2020-6-24 19:37:05 来自手机 | 显示全部楼层
落叶知秋 发表于 2020-6-24 19:27
定时器里面最后不要有弹窗,一定要弹窗的话也应该做好保护,好像是定时器消息在调用界面阻塞线程后,系统会 ...

windows的弹窗并不阻塞当前线程,只阻塞当前的这个处理函数。弹岀对话框以后,这个对话框会自带消息循环,让这个线程继续正常处理消息。如果真的阻塞当前线程,这个窗囗就完全无法操作了。

出0入20汤圆

发表于 2020-6-24 20:17:20 | 显示全部楼层
正确姿势是ManualResetEvent

出40入42汤圆

发表于 2020-6-24 20:18:46 来自手机 | 显示全部楼层
redroof 发表于 2020-6-24 19:37
windows的弹窗并不阻塞当前线程,只阻塞当前的这个处理函数。弹岀对话框以后,这个对话框会自带消息循环 ...

这个我知道,定时器弹窗后,那一次的消息路由直接传递到窗口里去了,定时器不会停下来不动,会继续响应新的消息。阻塞是我说错了,就是程序逻辑堵在弹窗那里不往下走

出300入477汤圆

发表于 2020-6-24 21:13:15 来自手机 | 显示全部楼层
落叶知秋 发表于 2020-6-24 20:18
这个我知道,定时器弹窗后,那一次的消息路由直接传递到窗口里去了,定时器不会停下来不动,会继续响应新 ...

没堵在那里啊,而是在那里重新进消息循环,然后重新进入自己,就是递归。
一个简单的防止递归进入的办法是在里面放个静态变量,进去置1,岀来前清零,下次递归进来了见到是1就直接退岀。
当然在定时器里弹窗确实不是个好方法,谁知道还有没有什么函数不能被递归调用的。。。

出0入8汤圆

发表于 2020-6-24 21:33:49 | 显示全部楼层
弹出MessageBox并不会阻塞当前线程,所以定时器消息依然能够得到处理,导致不断重入定时器的消息响应函数。应该大多都是使用12楼上说的方法,使用一个标志变量记录是否消息框已经弹出,否则继续。

出40入42汤圆

发表于 2020-6-24 21:41:28 来自手机 | 显示全部楼层
redroof 发表于 2020-6-24 21:13
没堵在那里啊,而是在那里重新进消息循环,然后重新进入自己,就是递归。
一个简单的防止递归进入的办法 ...

emmm,可能是我没表达好,“堵在那里”是指的那一次定时器里的程序逻辑卡在弹窗那里不往下走,要等窗口返回后才继续往下走……
反正以前是遇到过这个问题的,然后查了下资料

出0入0汤圆

发表于 2020-6-25 22:35:21 来自手机 | 显示全部楼层
弹窗前先关定时器,关闭弹窗后再重新打开定时器

出0入76汤圆

发表于 2020-6-26 09:40:43 | 显示全部楼层
timer定时事件函数是在系统自动开的另外一个线程运行的, 如果你里面有阻塞或比较耗时的操作(超过定时时长),将导致事件函数被多次触发运行。
解决办法:
方法一:
1)进入事件函数时,把定时器关闭
2)处理完成后退出时,再把定时器打开
方法二:
使用系统的锁的方式,或自己自制锁简单的临界保护,如下:
if (lock == true) return;
lock = true;
// your code ...
lock = false;

出0入0汤圆

发表于 2020-6-26 09:44:25 | 显示全部楼层
那么多人说Messagebox 不会阻塞啊。 Messagebox 是 阻塞得啊。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 05:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表