我在这里看到过许多这类问题的提问和回答,但这些问题似乎都解决不了我的问题。
我有一个从数据库中检索和显示数据列表的页面。我的初始代码如下所示
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 )。
private void HistoryPage_OnLoaded(object sender, RoutedEventArgs e)
{
//''''''''
new Thread(() =>
{
_invoices = Invoice.GetAll();
InvoiceList = new PagingCollection<Invoice>(_invoices, _itemsPerPage);
DgInvoices.ItemsSource = InvoiceList.CurrentItems;
}).Start();
}将引发此异常。
调用线程无法访问此对象,因为另一个线程拥有它。
在四处搜寻之后,我发现调度员就是解决这个问题的方法。但我不能让它起作用。
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();
}这仍然会引发上述异常。
你能推荐一种办法让这件事发挥作用吗?
发布于 2020-04-17 23:26:05
我个人认为BackgroundWorker是最好的选择。Dispatcher可能会工作,但它在WPF中是一个更“强制”的操作,有时还会出现一系列其他问题。使用BackgroundWorker,您可以在后台完成数据工作,然后在主线程上完成UI工作。
例如:
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。
发布于 2020-04-17 17:44:01
为什么在新线程中使用Dispatcher?
您可以简单地在新线程之外使用Dipatcher。
如下所示:
Dispatcher.Invoke(() =>
{
DgInvoices.ItemsSource = InvoiceList.CurrentItems;
});这样就可以在主线程上调用,而不是在新线程上调用。
发布于 2020-04-18 07:49:38
不要在线程中直接更新DgInvoices.ItemsSource。相反,将ItemSource绑定到属性并更新线程中的属性。
https://stackoverflow.com/questions/61277436
复制相似问题