2010-05-18 65 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)介绍如何使用它。