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);
}
答案 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);
}
但是,这确实需要您的数据库层与线程无关。如果它缓存某个数据库连接或某个与特定线程相关的东西,那么这种方法就无法工作。