为什么没有后台工作人员的UI没有及时更新?

时间:2017-04-03 14:01:27

标签: c#

我写了一个单线程程序(winforms meh),我希望它的行为如下:

  1. Mainform启动进度显示表单
  2. 完整呈现进度表单
  3. 进度表格接收事件操作开始向表格添加旋转圆圈的图片
  4. 持续运作开始
  5. 进度表单接收事件operationCompleted或operationFailed并设置相应的图像
  6. 发生的事情很乱。

    1. Mainform启动进度显示表单
    2. 进度表单未完全呈现!
    3. 程序暂停一段时间
    4. 当持久操作完成UI更新
    5. 为什么更新窗口的延迟会形成?

      如果需要,这是减少的代码

          private bool Run(int commandIndex, string fullCommand)
          {
              if (operationStarted != null)
                  operationStarted(commandIndex);
      
              // start long lasting external process
      
              if (exitCode != 0)
              {
                  if (operationFailed != null)
                      operationFailed(commandIndex, Error);
      
                  return false;
              }
      
              if (operationCompleted != null)
                  operationCompleted(commandIndex);
      
              return true;
          }
      

      operationStarted,operationFailed& operationCompleted已正确设置以更新相应的图像。

1 个答案:

答案 0 :(得分:2)

这大大简化了,但我认为它应该足够了。

Windows由在队列系统中处理的消息驱动。

显示窗口时,会将一条或多条消息放入队列并进行处理。

其中一条消息将成为绘画消息。响应此消息,您的程序应该在屏幕上绘制窗口(或其中的某些内容)。

处理队列系统的方式是您的表单由一个持续执行以下操作的线程拥有:

while (true)
{
    var message = GetNextMessage();
    if (message == none) break;
    ProcessMessage(message);
}

此循环处理的消息之一是一条消息,指示您的程序用户点击了表单上的按钮。

为此,.NET将此消息作为事件路由到您的事件处理程序,通常类似“button1_Click”,然后执行。

直到你的事件处理程序,这个click方法返回,这个循环不处理任何消息。

因此,如果那个按钮点击事件做了很长时间的事情,你会被称为“阻止UI”,这基本上是“你没有以有序的方式返回到消息循环”。