2017-04-03 28 views
0

我写了一个单线程程序(的WinForms MEH)和我期待它的表现是这样的:为什么没有后台工作人员不及时更新UI?

  1. 的MainForm开始进展显示形式
  2. 进展的形式呈现完全
  3. 进展形式receieves事件operationStarted这增加一张转圈图片
  4. 长效手术开始
  5. 进度表接收事件操作完成或操作失败并设置合适的图像

会发生什么是混乱。

  1. MainForm的进展开始显示形式
  2. 进展形式不完全呈现!
  3. 计划了一段时间
  4. 挂起当持久操作完成UI更新

为什么用更新的Windows窗体的滞后?

此减小的代码,如果必要

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

您需要一个BackGroundWorker。你的_long_operations操作和UI一样运行在同一个线程中,所以它阻塞了线程来阻止UI被刷新 – Pikoh

+0

问题是你的程序一步接一步地工作,所以它开始显示进度,之后甚至在它的渲染会启动您的持久操作并关闭您的操作,完成后,它会返回以继续显示UI。你需要一个Backgroundworker,它可以在另一个线程上执行此操作 –

回答

2

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

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

当您显示一个窗口时,一个或多个消息被放入一个队列并且必须被处理。

其中一条消息将成为一条消息。为了响应这个消息,你的程序应该在屏幕上绘制窗口(或者其中的东西)。

队列系统的处理方式是,你的形式是由一个线程,不断做类似资:

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

一个这个循环处理是一个消息,指示你的程序的消息的用户点击一个表格按钮。

作为对此的回应,.NET将此消息作为事件传递给事件处理程序,通常类似于“button1_Click”,然后执行该事件。

直到你的事件处理程序,这个click方法返回,这个循环没有处理任何消息。因此,如果该按钮点击事件做了很长时间的事情,那么你会被称为“阻止UI”,这基本上是“你没有按顺序返回到消息循环”。

相关问题