2008-08-13 72 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); 
} 
相關問題