2011-11-08 14 views
1

我有以下設置:觀察集合(綁定到Datagid) - 錯誤線程

public class Monitor 
{ 
    public ObservableCollection<People> listOfPeople = new ObservableCollection<People>(); 


    public dosomework() { 
     Thread t = new ThreadStart(longwork); 
     t.Start(); 
    } 

    public longwork() { 
     listOfPeople.Add(new People()); 
     Thread.Sleep(10000); 

    } 

} 

public class People : INotifyPropertyChanged 
{ 
    int _age; 
    public int Age 
    { 
     get { return _age; } 
     set 
     { 
      _age = value; 
      Notify("Age"); 
     } 
    } 
} 

public class UI : Window 
{ 
    Monitor md = new Monitor(); 
} 

我要綁定一個DataGrid來觀察集合(datagrid.ItemSource = md.listOfPeople),但是,我得到一個線程錯誤。此外,如果我不在新線程上進行長時間的工作,那麼界面只會在長工作完成後纔會更新。我認爲綁定可以避免這個問題。

任何幫助表示讚賞。

+0

此問題可以幫助:http://stackoverflow.com/questions/7994638/update-ui-async/7995272#7995272 – MichaelS

回答

1

正如其他人所說的,如果您在除UI之外的其他線程上做任何工作,則必須調度到UI線程以實際更新綁定到UI元素的任何元素。

在你的例子中,這相當簡單。只需通過Dispatchermsdn)你的窗口到您的Monitor並使用相應分派:

... 
Monitor md = new Monitor(this.Dispatcher); 
... 
public Monitor(Dispatcher dispatcher) 
{ 
    _dispatcher = dispatcher; 
} 
... 
public longwork() { 
    _dispatcher.BeginInvoke((Action)(()=>listOfPeople.Add(new People())); 
    Thread.Sleep(10000); 

} 

你可以稱之爲Dispatcher.Invoke代替Dispatcher.BeginInvoke,但如果你不關心結果,你要移動快,BeginInvoke是你的朋友。

1

綁定只是「其他代碼正在偵聽更改」,所以線程仍然是一個問題。

通常的修復方法是添加到UI線程的列表中,因爲這是網格將從中偵聽的位置,但如果爲單個元素運行,這會給性能帶來不好的影響。

最好將添加到後臺線程上運行的臨時列表中,然後每間隔(每100個項目?)調用AddRange以將該批次移動到UI集合以提供更好的響應並定期更新DataGrid。

0

數據綁定數據網格已訂閱到CollectionChanged事件。根據我的經驗,CollectionChanged事件在引發集合更改的任何線程上引發。在這種情況下,它不是UI線程。由於UI元素只能從UI線程修改,並且事件在非UI線程中引發和處理,因此會出現「線程錯誤」。

如上所述,一個簡單的解決方案是僅從UI線程修改ObservableCollection。

如果您使用的是WPF或Silverlight,則所有FrameworkElements都具有可用於在UI線程上執行工作的Dispatcher屬性。另見:http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject.aspx