2008-08-13 31 views
4

我正在研究一个应用程序,它可以从外部服务器获取并安装一堆更新,并且需要一些线程帮助。用户按照该过程:精简框架/线程 - 选择选项后,MessageBox显示在其他控件上

  • 点击按钮
  • 更新方法检查,返回计数。
  • 如果大于0,则询问用户是否要使用MessageBox.Show()进行安装。
  • 如果是,它会运行一个循环并在每个更新的run()方法上调用BeginInvoke()以在后台运行它。
  • 我的更新类有用于更新进度条等

进度条的更新精细一些事件,但在MessageBox没有从画面,因为该更新循环后,右开始完全清除用户点击是(见下面的截图)。

  • 我应该怎么做才能让消息框在更新循环开始之前即刻消失?
  • 我应该使用线程而不是BeginInvoke()吗?
  • 我应该在单独的线程上执行初始更新检查并从该线程调用MessageBox.Show()?

代码

// Button clicked event handler code... 
DialogResult dlgRes = MessageBox.Show(
    string.Format("There are {0} updates available.\n\nInstall these now?", 
    um2.Updates.Count), "Updates Available", 
    MessageBoxButtons.YesNo, 
    MessageBoxIcon.Question, 
    MessageBoxDefaultButton.Button2 
); 

if (dlgRes == DialogResult.Yes) 
{ 
    ProcessAllUpdates(um2); 
} 

// Processes a bunch of items in a loop 
private void ProcessAllUpdates(UpdateManager2 um2) 
{ 
    for (int i = 0; i < um2.Updates.Count; i++) 
    { 
     Update2 update = um2.Updates[i]; 

     ProcessSingleUpdate(update); 

     int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count); 

     UpdateOverallProgress(percentComplete); 
    } 
} 

// Process a single update with IAsyncResult 
private void ProcessSingleUpdate(Update2 update) 
{ 
    update.Action.OnStart += Action_OnStart; 
    update.Action.OnProgress += Action_OnProgress; 
    update.Action.OnCompletion += Action_OnCompletion; 

    //synchronous 
    //update.Action.Run(); 

    // async 
    IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); }); 
} 

截图

Windows Mobile Bug

回答

6

你的UI没有更新,因为所有的工作都在用户界面线程发生。 您对呼叫:

this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); }) 

是说创造了“本”(表单)线程,这是用户界面线程上调用update.Action.Run()。

Application.DoEvents() 

确实会给UI线程重绘屏幕的机会,但我很想创建新的委托,并调用BeginInvoke上。

这将在从线程池分配的单独线程上执行update.Action.Run()函数。然后,您可以继续检查IAsyncResult,直到更新完成,在每次检查后查询更新对象的进度(因为您无法让其他线程更新进度条/ UI),然后调用Application.DoEvents()。

你也应该调用EndInvoke()之后,否则你可能会泄漏资源

我也很想把取消的进度对话框按钮,添加一个超时,否则如果更新得到卡住(或需要太长时间),那么你的应用程序将永远锁定。

1

你试过把一个

Application.DoEvents() 

在这里

if (dlgRes == DialogResult.Yes) 
{ 
    Application.DoEvents(); 
    ProcessAllUpdates(um2); 
} 
相关问题