额外线程中的绑定项不能从调度程序线程中删除

时间:2013-12-16 13:10:45

标签: wpf dispatcher icollectionview

RefreshItems从ViewModel的构造函数中调用,并在用户希望时(RefreshCommand点击按钮)。

删除也绑定到DeleteCommand

我想刷新新线程中的项目,因为有些动画不是流畅的。

因此,绑定不会发生在调度程序的线程上,但是删除会发生,删除会抛出异常(请参阅代码)。

(TPL(async / await)是没有选项,因为必须支持XP。)

    public void RefreshItems()
    {
        new Thread(new ThreadStart(() =>
        {
            IsRefreshing = true;

            var items = _db.GetItems();

            var itemsCollectionView = CollectionViewSource
                .GetDefaultView(new ObservableCollection<ItemType>(items));

            Items = itemsCollectionView;

            IsRefreshing = false;
        })).Start();
    }

    private void Delete(ItemType item)
    {
        _db.DeleteItem(item);

        var items = (ObservableCollection<ItemType>)Items.SourceCollection;

        // InnerException: NotSupportedException
        // Message: This type of CollectionView does not support changes
        //          to its SourceCollection from a thread different from
        //          the Dispatcher thread.
        items.Remove(item);
    }

1 个答案:

答案 0 :(得分:2)

我发现最好将数据绑定项视为UI的一部分。因此,不应该从后台线程访问任何数据绑定。

理想情况下,您的数据库访问将使用类似EF6的东西,它支持异步方法。但是,由于您没有async数据库层,因此您可以使用&#34;假异步&#34;将(同步)数据库工作推送到后台线程的方法:

public async Task RefreshItemsAsync()
{
    IsRefreshing = true;

    var items = await Task.Run(() => _db.GetItems());

    var itemsCollectionView = CollectionViewSource
        .GetDefaultView(new ObservableCollection<ItemType>(items));

    Items = itemsCollectionView;

    IsRefreshing = false;
}

private async Task DeleteAsync(ItemType item)
{
    await Task.Run(() => _db.DeleteItem(item));

    var items = (ObservableCollection<ItemType>)Items.SourceCollection;

    items.Remove(item);
}

但是,这确实需要您的数据库层与线程无关。如果它缓存某个数据库连接或某个与特定线程相关的东西,那么这种方法就无法工作。