求助!!这回真的被System.Timers.Timer给玩死了!!

dongguacha 2011-05-09 09:58:49
我的程序里调用了一个 System.Timers.Timer ,在它的Elapsed事件里我试图用代码来模拟点击一个主窗口的按钮,bt_1.PerformClick(); 目的是在指定的时刻运行一段代码

程序结构:

private void TimeEvent(object source, ElapsedEventArgs e) //每秒激发一次
{
//检查时间SignalTime

if 到了指定时间
{
//这里加了一行代码在主窗口中打一句话标明程序运行到此处,便于观察
richTB.AppendText("系统状态:试图启动中...");

bt_1.PerformClick(); //执行按钮代码
}

}

程序运行时很奇怪,如果指定的时间不远,例如半小时内,那么一切都没问题,按钮代码如期被执行,但只要指定的时间比较长,例如好几个小时以后,那么就会出现"系统状态:试图启动中...",但按钮代码却没有被执行??即便我加上try catch 结构,也捕获不到异常。

我有怀疑是线程的问题,尝试了用委托来代替直接的 bt_1.PerformClick(); ,但问题依旧存在。。。。。。

实在是百思不得其解,希望有高手能给予指点,先谢谢啦!!
...全文
520 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
dongguacha 2011-05-10
  • 打赏
  • 举报
回复
谢谢isjoe的提醒!

第一种情况,不知道哪里有这个补丁?

第二种情况,我也考虑过,所以在Elapsed事件里放了个“richTB.AppendText("系统状态:试图启动中...");”这一行代码在指定时间里都能被运行,按理说Timer线程应该没有丢弃。

按钮所在的线程会不会被丢弃呢,但那是主窗口,属于UI线程吧,不应该被丢弃吧??
dongguacha 2011-05-10
  • 打赏
  • 举报
回复
这些都没说到重点呀,因为问题的关键是——在一定时间内,运行正常(得不得了);而超出一定时间后就不行了

UI线程的问题,只要不用WINDOWS.FORM.TIMER就可以了,SynchronizingObject 别指定,默认就行。
isjoe 2011-05-10
  • 打赏
  • 举报
回复

摘自msdn ,这句很重要,貌似微软并不推荐改计时器用在UI中,我在比的博客中也看到类似的说法。


如果和用户界面元素(如窗体或控件)一起使用 Timer,请将包含有 Timer 的窗体或控件赋值给 SynchronizingObject 属性,以便将此事件封送到用户界面线程中。

Timer 在运行时是不可见的。


isjoe 2011-05-10
  • 打赏
  • 举报
回复

摘自MSDN

应用于此类的 HostProtectionAttribute 属性 (Attribute) 具有以下 Resources 属性 (Property) 值:Synchronization | ExternalThreading。HostProtectionAttribute 不影响桌面应用程序(这些应用程序通常通过双击图标、键入命令或在浏览器中输入 URL 来启动)。有关更多信息,请参见 HostProtectionAttribute 类或 SQL Server 编程和主机保护属性。


Timer 组件是基于服务器的计时器,它使您能够指定在应用程序中引发 Elapsed 事件的周期性间隔。然后可以操控此事件以提供定期处理。例如,假设您有一台关键性服务器,必须每周 7 天、每天 24 小时都保持运行。可以创建一个使用 Timer 的服务,以定期检查服务器并确保系统开启并在运行。如果系统不响应,则该服务可以尝试重新启动服务器或通知管理员。

基于服务器的 Timer 是为在多线程环境中用于辅助线程而设计的。服务器计时器可以在线程间移动来处理引发的 Elapsed 事件,这样就可以比 Windows 计时器更精确地按时引发事件。有关基于服务器的计时器的更多信息,请参见“基于服务器的计时器介绍”。

基于 Interval 属性的值,Timer 组件引发 Elapsed 事件。可以处理该事件以执行所需的处理。例如,假设您有一个联机销售应用程序,它不断向数据库发送销售订单。编译发货指令的服务分批处理订单,而不是分别处理每个订单。可以使用 Timer 每 30 分钟启动一次批处理。

注意
当 AutoReset 设置为 false 时,Timer 只在第一个 Interval 过后引发一次 Elapsed 事件。若要保持以 Interval 时间间隔引发 Elapsed 事件,请将 AutoReset 设置为 true。


Elapsed 事件在 ThreadPool 线程上引发。如果 Elapsed 事件的处理时间比 Interval 长,在另一个 ThreadPool 线程上将会再次引发此事件。因此,事件处理程序应当是可重入的。

注意
在一个线程调用 Stop 方法或将 Enabled 属性设置为 false 的同时,可在另一个线程上运行事件处理方法。这可能导致在计时器停止之后引发 Elapsed 事件。Stop 方法的示例代码演示了一种避免此争用条件的方法。


如果和用户界面元素(如窗体或控件)一起使用 Timer,请将包含有 Timer 的窗体或控件赋值给 SynchronizingObject 属性,以便将此事件封送到用户界面线程中。

Timer 在运行时是不可见的。

有关 Timer 的实例的初始属性值列表,请参见 Timer 构造函数。

isjoe 2011-05-10
  • 打赏
  • 举报
回复
微软:
http://support.microsoft.com/kb/842793

。net三种计时器的差异:
http://sexycoding.iteye.com/blog/550155

另外好好看看MSDN中关于System.Timers.Timer 的解释
子夜__ 2011-05-09
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 dongguacha 的回复:]

引用 2 楼 icedmilk 的回复:
你为什么不到了指定时间直接调用一个函数?


因为懒嘛,我试试把按钮代码独立出来成为一个方法,再用TIMER调用
[/Quote]


把richTB.AppendText("系统状态:试图启动中...");这句干掉后 看效果如何
dongguacha 2011-05-09
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 icedmilk 的回复:]
你为什么不到了指定时间直接调用一个函数?
[/Quote]

因为懒嘛,我试试把按钮代码独立出来成为一个方法,再用TIMER调用
子夜__ 2011-05-09
  • 打赏
  • 举报
回复
运行时间长消耗系统资源啊
Icedmilk 2011-05-09
  • 打赏
  • 举报
回复
你为什么不到了指定时间直接调用一个函数?
anbam 2011-05-09
  • 打赏
  • 举报
回复
按钮代码却没有被执行 // 你如何判断没有被执行
isjoe 2011-05-09
  • 打赏
  • 举报
回复
第一.我发现微软的一份文档如下:是说System.Timers.Timer 存在bug的问题.(不过仅限.net 1.0 or 1.1)

您可以使用 Microsoft.net 框架来创建新的 Microsoft Windows 服务包含 System.Timers.Timer 对象。当您运行此新的 Windows 服务,可能不会引发 System.Timers.Timer 类的 Elapsed 事件。
需要打一个.net的补丁,如果你使用的不是.net 1.0 or 1.1就不属于这个问题.

假设你确定半个小时可以执行,时间久了就不行!!!
第二.这里是不是存在这样一个问题:
System.Timers.Timer和UI计时器不一样,实际它是ThreadPool的实现,
如果一个线程在线程池中很久没有被调用,ThreadPool到底会对他做什么呢?会不会丢弃它呢?
我猜测而已....
dongguacha 2011-05-09
  • 打赏
  • 举报
回复
这句是临时加上去,方便观察流程的...

17,740

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧