对象由另一个线程拥有

本文关键字:拥有 线程 另一个 对象 | 更新日期: 2023-09-27 18:07:30

我对线程的想法相当陌生,我正在使用BackgroundWorker,试图在完成一些工作时显示进度条。以下是BackgroundWorkerDoWork事件:

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是唯一的其他方法。

相关文章: