首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从另一个线程更新数据栅格的ItemSource

从另一个线程更新数据栅格的ItemSource
EN

Stack Overflow用户
提问于 2020-04-17 17:37:37
回答 4查看 651关注 0票数 1

我在这里看到过许多这类问题的提问和回答,但这些问题似乎都解决不了我的问题。

我有一个从数据库中检索和显示数据列表的页面。我的初始代码如下所示

代码语言:javascript
复制
   private void HistoryPage_OnLoaded(object sender, RoutedEventArgs e)
    {
       //''''''
        _invoices = Invoice.GetAll(); // returns a list of invoices
         InvoiceList = new PagingCollection<Invoice>(_invoices, _itemsPerPage);
        DgInvoices.ItemsSource = InvoiceList.CurrentItems;
      //''''''''' 
    }

在数据列表变大之前,这是正常的。现在这个操作大约需要6-8秒。然后,我尝试从不同的线程中获取数据,并从那里更新数据格力( DGInvoices )。

代码语言:javascript
复制
   private void HistoryPage_OnLoaded(object sender, RoutedEventArgs e)
    {
       //''''''''

        new Thread(() =>
        {
            _invoices = Invoice.GetAll();
              InvoiceList = new PagingCollection<Invoice>(_invoices, _itemsPerPage);
            DgInvoices.ItemsSource = InvoiceList.CurrentItems;
        }).Start();
    }

将引发此异常。

调用线程无法访问此对象,因为另一个线程拥有它。

在四处搜寻之后,我发现调度员就是解决这个问题的方法。但我不能让它起作用。

代码语言:javascript
复制
    private void HistoryPage_OnLoaded(object sender, RoutedEventArgs e)
    {
       //''''''''
        new Thread(() =>
        {
            _invoices = Invoice.GetAll();
              InvoiceList = new PagingCollection<Invoice>(_invoices, _itemsPerPage);
            Dispatcher.Invoke(() =>
            {
                DgInvoices.ItemsSource = InvoiceList.CurrentItems;
            });

        }).Start();
    }

这仍然会引发上述异常。

你能推荐一种办法让这件事发挥作用吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-04-17 23:26:05

我个人认为BackgroundWorker是最好的选择。Dispatcher可能会工作,但它在WPF中是一个更“强制”的操作,有时还会出现一系列其他问题。使用BackgroundWorker,您可以在后台完成数据工作,然后在主线程上完成UI工作。

例如:

代码语言:javascript
复制
BackgroundWorker bw = new BackgroundWorker();

public MainWindow()
{
    InitializeComponent();

    //Subscribe to the events
    bw.DoWork += Bw_DoWork;
    bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
}

private void HistoryPage_OnLoaded(object sender, RoutedEventArgs e)
{
     //Start background worker on page load
     bw.RunWorkerAsync(); //This is the DoWork function
}

//Background worker executes on separate thread
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
     //Do long running operations
     _invoices = Invoice.GetAll();           
}

//Fires when the DoWork operation finishes. Executes on the main UI thread
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     //Update UI when the worker completes on the main thread
     InvoiceList = new PagingCollection<Invoice>(_invoices, _itemsPerPage);
     DgInvoices.ItemsSource = InvoiceList.CurrentItems;
}

如果您的操作变得非常长,您甚至可以访问BackgrounWorker.ReportProgess操作并向UI提供状态更新。这是一个很好的工具来加载操作,您可以使用它来避免锁定UI。

票数 1
EN

Stack Overflow用户

发布于 2020-04-17 17:44:01

为什么在新线程中使用Dispatcher?

您可以简单地在新线程之外使用Dipatcher。

如下所示:

代码语言:javascript
复制
Dispatcher.Invoke(() =>
        {
            DgInvoices.ItemsSource = InvoiceList.CurrentItems;
        });

这样就可以在主线程上调用,而不是在新线程上调用。

票数 0
EN

Stack Overflow用户

发布于 2020-04-18 07:49:38

不要在线程中直接更新DgInvoices.ItemsSource。相反,将ItemSource绑定到属性并更新线程中的属性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61277436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档