1

私はスレッドのアイデアにかなりBackgroundWorker慣れていません。いくつかの作業が行われている間にプログレスバーを表示しようとしています。のDoWorkイベントは次のBackgroundWorkerとおりです。

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 要素も他の要素で使用されるべきではありません。私の質問は、2 つのメソッドを同じにラップできDispatcher.Invoke()ますか? ただし、正直なところ、同じ関数でこれらの呼び出しを 2 つ使用するべきではないと感じています。私がやろうとしていることについてもっと良い方法はありますか?

4

1 に答える 1

3

バックグラウンド ワーカーの ProgressChanged イベントを介してデータを返すことができます。これにより、UI スレッドにマーシャリングされます。このドキュメントでは、 ReportProgressを呼び出してこのイベントを呼び出していることがわかります。

BackgroundWorker'sでのみビジネスロジックを実行する必要があることに注意してくださいDoWork。UI を更新するだけの場合は、バックグラウンド スレッドでこれを行うことはできません。データを取得する必要がある場合は、バックグラウンド ワーカーを使用してそれをメモリに読み込むことができます。完了すると、接続されている場合はOnRunWorkerCompletedイベントが呼び出されます (これは UI スレッドにあります)。

部分的にそれを行うある種のアプローチが必要な場合は、それInvokeが唯一の他の方法です。

于 2013-04-05T15:30:27.203 に答える