我目前有一个应用程序可以生成单个win表单的多个实例。表单的每个实例都有一个计时器,它以大约1 tick / sec的速率更新表单本身的一些控件和一些属性。一旦应用程序达到一定数量的表单,它就会停止绘制计时器滴答内发生的“更新”。
我想在计时器的底部保持UI线程并允许表单重新绘制而不调用Application.DoEvents(我的理解是Application.DoEvents()处理所有挂起的窗口消息应用程序(可能包括其他计时器'滴答'? - 不确定)当我想要它处理的是重新绘制表单,因为已经更新了许多控件。
答案 0 :(得分:5)
如果您只想让表单或特定控件重绘,只需在相关表单/控件上调用Control.Refresh即可。
话虽这么说,这通常(如Application.DoEvents)是重新设计有序的标志。如果您有这样的长时间运行流程,那么将工作推送到BackgroundWorker会更好,这将使实际的计算工作在后台线程中运行,并防止UI变得无响应。
答案 1 :(得分:5)
我不清楚你为什么要打电话给DoEvents
。为什么不让窗口重新贴合自己呢?它目前的行为方式有什么问题?
调用DoEvents
通常表示某些内容应该在后台线程中 - 在您的情况下,听起来实际上可能只是您发生了太多事件。如果您的GUI非常复杂,以至于无法在一秒钟内重绘,那听起来这可能是UI本身的设计问题。
答案 2 :(得分:3)
消息循环调用了三类Windows消息,并调用了Application.DoEvents()。首先是使用SendMessage()发送的消息。它们很重要,它们需要立即发送,因为有一些其他程序正在等待SendMessage()调用的结果。它们没有放在消息队列中,Windows直接调用窗口过程。
然后使用PostMessage()将消息放在消息队列中。他们可以等待,他们只是通知。所有键盘和鼠标消息都符合该类别。
然后是低优先级消息,WM_TIMER和WM_PAINT。只有当没有其他事情要做,没有SendMessage挂起且消息队列为空时,它们才会被调度。
听起来你已经陷入了这样一种情况,即你如此严重地使Windows挨饿,以至于无法再将这些低优先级消息发送出去。可能既没有得到计时器Ticks也没有Paint事件。每秒只调用一次DoEvents肯定会这样做。这很糟糕,你的程序现在也影响了其他程序的运行。你必须解决这个问题。通过重新设计您的应用程序,使您不再依赖DoEvents来实现这一目标。
答案 3 :(得分:0)
我的2c:
每种形式都有一个计时器会使性能降低到爬行速度。每隔一个时间间隔的每个窗口将请求应用程序切换到该窗口的“上下文”并执行一些代码。整个开关可能比您的代码实际运行时间长。结合所有形式都在同一“背景”中的可能事实。
如果可能,请考虑这样的事情:
List<MyForm> listofmyform;
Timer t = new Timer()
t.tick += delegate
{
foreach(MyForm thisform in listofmyform)
thisform.DoUpdate();
}
这只使用一个计时器来更新所有表单,只需要一个“上下文切换”,可能会解决您遇到的一些性能问题。