如何使用 WPF 中的任务正确刷新网格中的数据

How to correctly refresh data in a grid using Task in WPF

我的小 WPF 代码给我这个错误 调用线程无法访问此对象,因为另一个线程拥有它 我知道它到底在说什么,但我无法理解如何修复它。我尝试了不同的东西但没有运气,我承认我在任务库中表现不佳。

这就是我想要达到的目标。

  1. 加载 WPF 表单时加载数据 - 这没问题
  2. 在表单上,​​用户将按下 刷新 按钮以刷新数据库中的数据。

这是我的代码

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;
    }}

实际上,当我在这一行单击刷新按钮时出现错误 _scecoBillDataScope.FetchData(); 请指教。

你的问题是这一行:

await Dispatcher.BeginInvoke(new ThreadStart(()=> LayoutRoot.DataContext = collectionView));

你只是在创建一个新线程,你必须在 GUI 线程上实际调度:

Application.Current.Dispatcher.Invoke(() =>
{
    LayoutRoot.DataContext = collectionView;
});

您似乎想在 UI 话题中做点什么。

如您所知,您可以使用 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);

希望对您有所帮助。

谢谢。

由于您的 collection 项目是与您的视图绑定的数据,因此您必须将它们视为 UI 的一部分。

尝试从 Task.Run 中加载新的 collection,然后在 UI 线程中将它们复制到现有项目上。所以,新的collection建立在一个线程池线程(Task.Run)上,然后data-boundcollection项是从UI线程修改的。