首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Thread.Sleep或Thread.Timer挂起系统?

Thread.Sleep或Thread.Timer挂起系统?
EN

Stack Overflow用户
提问于 2014-08-05 04:10:37
回答 1查看 896关注 0票数 5

我已经环顾四周一个多星期了,我还没有找到其他人有类似的问题,我在这里看到。

我正在使用一个在Windows XP上运行并在Visual Studio2003中开发的旧应用程序。大约3周前,应用程序突然变得没有响应,操作员必须执行Windows三指致敬(CTRL-ALT-DEL)来启动任务管理器,终止应用程序进程(显示为无响应),然后重新启动应用程序。

这是对象以及它出现挂起的位置,这不是它在源代码中的编写方式

代码语言:javascript
复制
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周前。

还有没有人见过这种行为?

EN

回答 1

Stack Overflow用户

发布于 2014-11-17 04:19:48

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

代码语言:javascript
复制
internal static System.Windows.Forms.Timer timerMtimeOut;

没有充分的理由声明System.Windows.Forms.Timer静态,因为这个特定的计时器被设计为链接到特定的窗口(窗体实例),并且将导致在该窗体的主线程中触发tick事件。它通过在计时器到达节拍时向线程消息队列发送消息来实现这一点。然后,该消息与鼠标移动和键盘输入等所有其他消息一起在forms线程(WndProc)中进行处理。

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

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

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

有点离题,但变量的名称表明您正在尝试计算漫长过程中的间隔数?请注意,如果这个冗长的进程正在窗体的主线程中运行,则计时器的计时事件将在消息循环中排队,并且只有在冗长的进程完成其工作并恢复消息处理之后才会执行。您在注释中提到的使用DateTime字段的方法比使用计时器更简单、更安全、更好。

当你需要一个定时器来在时钟节拍被击中时立即执行代码时,你可以使用System.Threading.Timer而不是System.Windows.Forms.Timer。如果您需要从多个线程控制它,请使用System.Timers.Timer (该use是线程安全的)。请注意,这些计时器将在不同的线程中执行它们的事件。还要注意的是,除了窗体主线程之外,您永远不应该从其他线程操作控件或窗体。一种简单的方法是使用Control.Invoke()方法将其内置到框架中,该方法反过来将使用消息循环对操作进行排队。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25126736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档