WPF中一個很是強大的功能是數據綁定,咱們能夠把一個集合綁定到ListBox中,當集合的數據發生變動時,ListBox界面也會同步變動。自己這是一個很是美好的事情,可是美中不足的是:當把集合綁定到ListBox中的時候,集合也順帶繼承了ListBox的這種不能誇線程訪問的限制。例如,以下代碼就會拋出跨線程訪問異常。安全
解決這個問題的一個傳統方式是把對集合的修改Post到UI線程中來,改爲以下形式。async
ThreadPool.QueueUserWorkItem(async _ =>
{
await Task.Delay(1000);
this.Dispatcher.Invoke(new Action(()=>collection.Add(DateTime.Now.ToString())), null);
}); 函數
不過這種寫法顯得很繁瑣,在.Net 4.5提供了新的一種線程安全訪問機制,那就是用BindingOperations.EnableCollectionSynchronization使能集合同步: this
var collection = new ObservableCollection<string>();
listBox.ItemsSource = collection;
var lockObj = new object();
BindingOperations.EnableCollectionSynchronization(collection, lockObj);
ThreadPool.QueueUserWorkItem(async _ =>
{
await Task.Delay(1000);
collection.Add(DateTime.Now.ToString());
}); spa
這樣,對集合訪問就沒有UI線程限制了,要方便很多。沒有細研究其內部實現機制,貌似是經過加鎖實現的。 線程
與之相對的是,還提供了一個去使能集合同步的函數BindingOperations.DisableCollectionSynchronization。網上的文章說是使用完後要用這個函數去使能集合同步,不然會覺得集合的引用沒有釋放致使內存泄漏。不過,我本身寫代碼試了一下,即便不用它解除鎖定,集合對象仍是能正常釋放的,應該保存的只是一個弱引用,不主動解除鎖定也沒有內存泄漏問題。 對象