2012-11-23 37 views
0

我在Silverlight視圖中有一個TabControl,我通過將它的ItemsSource綁定到我的ViewModel中的TabItems ObservableCollection來加載Tabs。Silverlight中的BackgroundWorker ViewModel

要打開一個新選項卡,需要一段時間來創建它並加載它,同時我想運行一個BusyIndi​​cator。

由於它們是在ViewModel中創建和加載的,因此它在調用「load」方法之前設置IsBusy屬性時不顯示,因爲它不是異步的。

我試着在backgroundworker中設置它,但是當我創建TabItem將它添加到TabItems列表(UnauthorizedAccessException)時它崩潰了。

任何想法???提前致謝。

+0

你能發佈你的BGW代碼嗎? –

回答

2

使用任務(AsyncCtp with Silverlight 4):

public void Load(){ 
    this.IsBusy = true; 
    Task.Factory.StartNew(()=> DoHeavyWork()) 
     .ContinueWith(t => this.IsBusy = false); 
} 

它會變得更好,如果你可以使用新的異步/等待與異步CTP或VS2012/Silverlight 5

public async void Load(){ 
    try{ 
     this.IsBusy = true; 

     await Task.Factory.StartNew(()=> DoHeavyWork()); 
    } 
    finally 
    {  
     this.IsBusy = false; 
    } 
} 

編輯

功能

我假設你正在更新後臺任務中的ObservableCollection。這確實會給你帶來問題,因爲處理集合更新的處理程序沒有在UI線程中運行,所以集合更新與綁定系統不是線程安全的。爲了達到這個目的,你必須將這些項目添加到UI線程的ObservableCollection中。如果你能一次獲取所有的物品,你可以這樣做:

public async void Load(){ 
    try{ 
     this.IsBusy = true; 

     // Returns the fetched items 
     var items = await Task.Factory.StartNew(()=> DoHeavyWork()); 

     // This will happen in the UI thread because "await" returns the 
     // control to the original SynchronizationContext 
     foreach(var item in items) 
      this.observableCollection.Add(item); 
    } 
    finally 
    {  
     this.IsBusy = false; 
    } 
} 

如果您有批量加載,您可以使用當前Dispatcher添加項目到集合,就像我在this answer建議。

+0

感謝您的回答。我已經嘗試了Async解決方案,但是當我創建一個新的控件時,我仍然遇到了UnauthorizedAccessException :-( – zapico

+0

)如果更新ObservableCollection,它將從UI線程以外的線程中爲Tab控件生成項目,那麼確實會導致你的問題請參閱編輯答案 –

+0

感謝您的深入解釋:) – zapico

0

當您嘗試訪問UI的元素或改變反過來反映在UI上的數據的集合時,會發生這種情況。這實際上是交叉線程異常。當你創建一個後臺工作者時,你基本上正在創建另一個線程。因此,您無法從後臺工作人員訪問主UI線程的變量。

+0

現在我們知道了爲什麼,你知道任何解決方案? – zapico

相關問題