加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Thread.Sleep或Thread.Timer挂系统?

发布时间:2020-12-15 22:06:53 所属栏目:百科 来源:网络整理
导读:我一直在寻找一个星期以上,而且我找不到其他人遇到类似问题的东西. 我正在使用在Windows XP上运行并在Visual Studio 2003中开发的OLD应用程序.大约3周前突然,应用程序无响应,运算符必须执行Windows三指致敬(CTRL-ALT- DEL)调出任务管理器,终止应用程序进程(
我一直在寻找一个星期以上,而且我找不到其他人遇到类似问题的东西.

我正在使用在Windows XP上运行并在Visual Studio 2003中开发的OLD应用程序.大约3周前突然,应用程序无响应,运算符必须执行Windows三指致敬(CTRL-ALT- DEL)调出任务管理器,终止应用程序进程(显示为Not Responding)并重启应用程序.

我设法让它在调试器中发生一次,当我暂停应用程序时,它正在等待系统从尝试设置System.Windows.Forms.Timer.Interval属性返回.

这是对象和它似乎挂起的地方,这不是它在源代码中的编写方式

internal static System.Windows.Forms.Timer timerMtimeOut;

// This is in an initialization method.
timerMtimeOut = new System.Windows.Forms.Timer();   
timerMtimeOut.Tick += new System.EventHandler(timerMtimeOut_Tick);

// this is how it's value is set.
timerMtimeOut.Interval = 1 * msec;  // <-- This is where it was in the debugger
timerMtimeOut.Enabled = true;


private static void timerMtimeOut_Tick(object sender,System.EventArgs e)
{           
    mTimeOut +=timerMtimeOut.Interval/msec;
}

应用程序基本上没有响应,必须使用任务管理器关闭并重新启动.

它已经很好地工作多年了,然后这种情况在2-3周前开始发生.

有没有人见过这种行为?

解决方法

最可能的原因是您以不是为其构建的方式使用计时器.第一行代码给出了一个提示:

internal static System.Windows.Forms.Timer timerMtimeOut;

没有充分的理由声明System.Windows.Forms.Timer静态,因为这个特定的计时器被设计为链接到特定的Window(Form实例),并将导致在该表单的主线程中触发tick事件.它通过在计时器命中时间点时将消息发送到线程消息队列来实现.然后在表单线程(WndProc)中处理该消息以及所有其他消息,例如鼠标移动和键盘输入.

如果您实例化多个访问计时器的窗口,那么问题迟早会出现.

当操作系统说进程没有响应时,它会通过查看主线程消息队列中的消息如何处理来检测到这一点.如果它们没有被处理,那么主线程正在运行一个冗长的例程,或者已经进入了一些无限循环.从主线程调用Thread.Sleep()(如问题标题中所述)将导致消息处理暂停(并且将阻止在睡眠期间处理滴答).

冗长的过程应该在一个单独的线程中运行,以保持应用程序的响应.您可能希望显示进度条,并为用户提供中止该过程的机会.如果在主线程中运行冗长的进程,这很难做到.通过在循环中的某处调用Application.DoEvents()可以实现一个肮脏的解决方法,它将动态处理消息队列.但是在使用此变通方法时,您应该非常小心地禁用UI按钮,否则您的用户可能会多次(递归地)启动该过程或更改您的过程所依赖的其他状态.

有点偏离主题,但变量的名称暗示你试图在漫长的过程中计算间隔的数量?请注意,如果在Form的主线程中运行该冗长的进程,则计时器的tick事件将在消息循环中排队,并且仅在冗长的进程完成其工作并且恢复消息处理之后才执行.您在DateTime字段的注释中提到的方法比使用计时器更简单,更安全,更好.

当你需要一个定时器,它会在命中时间点时立即执行代码,你可以使用System.Threading.Timer而不是System.Windows.Forms.Timer.如果你需要从多个线程控制它,请改用System.Timers.Timer(那个是线程安全的).请注意,这些计时器将在不同的线程中执行它们的事件.另请注意,除了表单主线程之外,您永远不应该从其他线程操作控件或表单.使用Control.Invoke()方法将一个简单的方法构建到框架中,该方法将使用消息循环对操作进行排队.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读