2010-05-18 67 views
3

我的代碼啓動後臺線程。後臺線程進行更改,並希望主線程中的UI更新。一個啓動然後線程等待的代碼看起來是這樣的:WPF:從後臺線程更新UI問題

   Thread fThread = new Thread(new ThreadStart(PerformSync)); 

       fThread.IsBackground = true; 
       fThread.Start(); 

       fThread.Join(); 

       MessageBox.Show("Synchronization complete"); 

當背景要更新UI,它設置一個StatusMessage並調用下面的代碼:

static StatusMessage _statusMessage; 
    public delegate void AddStatusDelegate(); 
    private void AddStatus() 
    { 
     AddStatusDelegate methodForUIThread = delegate 
     { 
      _statusMessageList.Add(_statusMessage); 
     }; 

     this.Dispatcher.BeginInvoke(methodForUIThread, System.Windows.Threading.DispatcherPriority.Send); 
    } 

_statusMessageList是一個ObservableCollection這是ListBox的來源。

AddStatus方法被調用,但主線程上的代碼從不執行 - 也就是說,當線程正在執行時,_statusMessage不會被添加到_statusMessageList。但是,一旦它完成(fThread.Join()返回),就會執行主線程上的所有堆積調用。

但是,如果我在fThread.Start()和fThread.Join()的調用之間顯示消息框,則狀態消息會正確更新。

我需要改變什麼,以便主線程中的代碼在等待線程終止的時候執行(UI更新)?

謝謝。

回答

4
fThread.IsBackground = true; 
fThread.Start(); 

fThread.Join(); 

對Join()的調用阻塞了您的主線程,直到後臺線程完成。所以當另一個線程運行時,UI線程無法做任何事情。你不需要調用Join()。如果您需要在後臺線程完成後在主線程上執行某些操作,請查找另一種方法來完成此操作。

編輯:它的工作原因,如果您顯示一個消息框之間的開始和加入的呼叫是因爲然後主線程運行消息框的消息循環,而不是在加入調用被阻止。

6

fThread.Join導致您的主線程阻塞,直到後臺線程完成。只要主線程被阻塞,UI就不能被更新。

你需要做的是這樣的(未經測試,但你應該明白我的意思):

void someUiEventThatCausesTheBackgroundProcessingToStart() { 
    Thread fThread = new Thread(new ThreadStart(PerformSync)); 
    fThread.IsBackground = true; 

    // disable some UI components here, so that the user cannot 
    // start the thread a second time 
    ... 

    fThread.Start(); 

    // *don't* call Thread.Join here, so that your main thread does not block! 
} 

void PerformSync() { 
    try { 
     // do your stuff here 
     ... 
    } finally { 
     Dispatcher.Invoke(new Action(ProcessingDone)); 
    } 
} 

void ProcessingDone() { 
    // re-enable the UI components 
    ... 

    MessageBox.Show("Synchronization complete"); 
} 

當然,在WPF,禁用/啓用UI組件使用一些IsBusyProcessing依賴屬性是理想做這勢必與觸發器所討論的UI元素,但這是另一個故事...

編輯:作爲另一種選擇,你可能想check outBackgroundWorker類,它包含ProgressChangedRunWorkerCompleted事件自動閃光在主要三廣告。

1

BackgroundWorker是此工作的最佳工具。它不是比絕對必要的更復雜,爲您提供進度報告所需的所有鉤子,並且有大量可用信息(如this answer)介紹如何使用它。