C# 如何使用WPF中的任务正确刷新网格中的数据
我的小WPF代码给了我这个错误 调用线程无法访问此对象,因为另一个线程拥有它 我知道它到底在说什么,但我无法理解如何修复它。我尝试过不同的事情,但没有运气,我承认我不擅长任务库 这就是我想要达到的目标C# 如何使用WPF中的任务正确刷新网格中的数据,c#,wpf,data-binding,devexpress,task,C#,Wpf,Data Binding,Devexpress,Task,我的小WPF代码给了我这个错误 调用线程无法访问此对象,因为另一个线程拥有它 我知道它到底在说什么,但我无法理解如何修复它。我尝试过不同的事情,但没有运气,我承认我不擅长任务库 这就是我想要达到的目标 加载WPF表单时加载数据-这是正常的 在表单上,用户将按下刷新按钮来刷新数据库中的数据 这是我的密码 public partial class DocListView : UserControlListBase { private ScecoBillDataScope _scecoBill
public partial class DocListView : UserControlListBase
{
private ScecoBillDataScope _scecoBillDataScope;
public EntityCollection<ScecoBillEntity> ScecoBills = new EntityCollection<ScecoBillEntity>();
public DocListView()
{
InitializeComponent();
LoadData();
}
private async void LoadData()
{
await Task.Run(() =>
{
_scecoBillDataScope.FetchData();
});
var collectionView = CollectionViewSource.GetDefaultView(_scecoBillDataScope.ScecoBills);
await Dispatcher.BeginInvoke(new ThreadStart(()=> LayoutRoot.DataContext = collectionView));
}
private void BbiRefresh_ItemClick(object sender, DevExpress.Xpf.Bars.ItemClickEventArgs e)
{
_scecoBillDataScope.Reset();
LoadData();
e.Handled = true;
}}
公共部分类DocListView:UserControlListBase
{
专用ScecoBillDataScope\u ScecoBillDataScope;
public EntityCollection ScecoBills=new EntityCollection();
公共文档列表视图()
{
初始化组件();
LoadData();
}
私有异步void LoadData()
{
等待任务。运行(()=>
{
_scecoBillDataScope.FetchData();
});
var collectionView=CollectionViewSource.GetDefaultView(\u scecoBillDataScope.ScecoBills);
等待Dispatcher.BeginInvoke(新线程开始(()=>LayoutRoot.DataContext=collectionView));
}
私有void BbiRefresh_ItemClick(对象发送者,DevExpress.Xpf.bar.ItemClickEventArgs e)
{
_scecoBillDataScope.Reset();
LoadData();
e、 已处理=正确;
}}
实际上,当我单击这一行的刷新按钮时,就会出现错误\u scecoBillDataScope.FetchData()强>
请给我一些建议 您的问题是这一行:
await Dispatcher.BeginInvoke(new ThreadStart(()=> LayoutRoot.DataContext = collectionView));
您只需创建一个新线程,就必须在GUI线程上实际调度:
Application.Current.Dispatcher.Invoke(() =>
{
LayoutRoot.DataContext = collectionView;
});
看起来您希望在UI线程中执行某些操作
var uiThread = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
// I assumed that It returns boolean value
_scecoBillDataScope.FetchData();
}).ContinueWith(x =>
{
// Here you can put the code to work on the UI thread.
if (x.Result)
{
var collectionView = CollectionViewSource.GetDefaultView(_scecoBillDataScope.ScecoBills);
LayoutRoot.DataContext = collectionView;
}
}, uiThread);
正如您所知,您可以使用Dispatcher
class
但是,还有另一种方法可以向UI线程请求某些内容
var uiThread = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
// I assumed that It returns boolean value
_scecoBillDataScope.FetchData();
}).ContinueWith(x =>
{
// Here you can put the code to work on the UI thread.
if (x.Result)
{
var collectionView = CollectionViewSource.GetDefaultView(_scecoBillDataScope.ScecoBills);
LayoutRoot.DataContext = collectionView;
}
}, uiThread);
我希望有帮助
谢谢。由于您的收集项目是绑定到视图的数据,因此您必须将其视为UI的一部分
尝试从
任务中加载新集合。运行,然后在UI线程上通过现有项目复制它们。因此,新集合构建在线程池线程(Task.Run
)上,然后从UI线程修改数据绑定集合项。Task.Run(()=>return FetchDataFromDB();)。继续((o)=>使用o.Result更新UI)您的FetchData()方法不应尝试更新其他线程所拥有的任何控件。@NawedNabiZada正如您所建议的,我做了此更改,但仍然没有成功,这是因为我的集合是INotifyChangedProperty感知的。private async void LoadData(){var collectionView=CollectionViewSource.GetDefaultView(_scecoBillDataScope.ScecoBills);wait Task.Run(()=>_scecoBillDataScope.FetchData()).ContinueWith((o)=>LayoutRoot.DataContext=collectionView);}那么FetchData()是什么呢
实际情况如何?@Shax由于您的收藏项目与视图相关联,因此您必须将它们视为UI的一部分。请尝试从任务中加载一个新集合。运行,然后在UI线程上复制它们到现有项目上。不,我的朋友没有解决我的问题,但感谢您花时间帮助我。不,我的朋友没有解决我的问题,感谢您花时间帮助我。is'\u scecoBillDataScope.FetchData();'在UI线程上运行?