在WPF 4.5中跨線程更新集合

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網上的文章說是使用完後要用這個函數去使能集合同步,不然會覺得集合的引用沒有釋放致使內存泄漏。不過,我本身寫代碼試了一下,即便不用它解除鎖定,集合對象仍是能正常釋放的,應該保存的只是一個弱引用,不主動解除鎖定也沒有內存泄漏問題。 對象

相關文章
相關標籤/搜索