对象由另一个线程拥有
本文关键字:拥有 线程 另一个 对象 | 更新日期: 2023-09-27 18:07:30
我对线程的想法相当陌生,我正在使用BackgroundWorker
,试图在完成一些工作时显示进度条。以下是BackgroundWorker
的DoWork
事件:
private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
{
SetDateStartEndTimeForReport();
try
{
PopulateGrid();
}
catch (Exception ex)
{
Logger.Error(ex.Message);
MessageBox.Show(ex.Message);
return;
}
}
现在,在我的SetDateStartEndTimeForReport()
中,我得到了InvalidOperationException
:
private void SetDateStartEndTimeForReport()
{
Logger.Info("Setting the chosen date and/or start/end times for report...");
// Quite possibly the best yo-yo code I've ever written
// "Look, I'm a string. Nope, I'm a DateTime. Tricked you again, I'm a string."
var reportDate = Convert.ToDateTime(cmbDateSelecter.SelectedValue.ToString()).ToString("yyyy-MM-dd"); // Exception occurs here
Report.Date = reportDate;
if (chkboxTimeFrame.IsChecked == true)
{
Report.StartTime = timeStart.Value.Value.ToString(reportDate + " HH:mm");
Report.EndTime = timeEnd.Value.Value.ToString(reportDate + " HH:mm");
}
Logger.Info("Date and/or start/end times set");
}
异常状态:
调用线程不能访问这个对象,因为它被另一个线程拥有。
所以,我做了一些研究,发现了this.Dispatcher.Invoke((Action)(()
。现在,当我把SetDateStartEndTimeForReport();
括起来时:
this.Dispatcher.Invoke((Action)(() =>
{
SetDateStartEndTimeForReport();
}));
我的PopulateGrid()
抛出同样的异常。现在,我可以将该方法包装在同一个Dispatcher.Invoke()
中,这样问题就解决了。然而,我觉得我好像错过了一些更……优雅。在函数调用的时候,UI元素不应该被其他任何东西使用。我的问题是,我可以在同一个Dispatcher.Invoke()
包装两个方法吗?不过,老实说,我觉得不应该在同一个函数中使用这两个调用。有没有更好的方法来做我想做的事?
你可以通过后台worker的ProgressChanged事件返回数据。这将封送回UI线程。该文档让您知道通过调用ReportProgress
来调用此事件请注意BackgroundWorker's
应该只在它们的DoWork
中做业务逻辑。如果你所做的只是更新UI,那么你就不能在后台线程中这样做。如果你需要检索数据,那么你可以使用后台worker将其加载到内存中,当完成时,它将调用OnRunWorkerCompleted事件,如果你将它连接起来(它将在UI线程上)
如果你想要某种方法来完成它的部分,那么Invoke
是唯一的其他方法。