0

私のアプリケーションのビジネスロジック層には、次のクラスがあります。

public class EocMonitor : DeviceMonitor {

    public BackgroundWorker BackendWorker { get; set; }

    public BackgroundWorker EocWorker { get; set; }

    public EocMonitor() {
        BackendWorker = new BackgroundWorker {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };
        BackendWorker.DoWork += BackendWorker_DoWork;

        EocWorker = new BackgroundWorker {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };
        EocWorker.DoWork += EocWorker_DoWork;
    }

    private void BackendWorker_DoWork( object sender, DoWorkEventArgs e ) {
        // Does some lengthy operation
    }

    void EocWorker_DoWork( object sender, DoWorkEventArgs e ) {
        // Does some lengthy operation
    }

    public void GetDiagnostics() {
        BackendWorker.RunWorkerAsync( new DiagnosticsInfo() );
            EocWorker.RunWorkerAsync( new DiagnosticsInfo() );
    }

}

public class DiagnosticsInfo {

    public int DataTypeCount { get; set; }

    public int DataTypesProcessed { get; set; }
}

これらBackgroundWorkersは、アプリケーションで実行されている他の2つのプロセスからネットワーク経由で情報を照会するために使用されます。応答が返ってくるまでに時間がかかる場合があります。さらに、データが返されるまでに時間がかかる場合があります。

アプリケーションのメインウィンドウに、と呼ばれるWPFUserControlがありますDashboardDashboardに はDataGrid、長い操作の結果を表示するがあります。それらは長いのでButton、プロセスを開始するリフレッシュと呼ばれるオンもあります。また、実行に時間がかかる可能性があるためProgressControl、フォームにaと呼ばれるUserControlがあります。これは、キャンセルButton,aProgressBarTextBlockメッセージを表示できる場所で構成されます。ユーザーが[キャンセル]をクリックするButtonと、更新が停止します。

ここにいくつかのコードがありますDashboard

public partial class Dashboard : UserControl {

    public Dashboard() {
        InitializeComponent();
    }

    private Dashboard_Loaded( object sender, RoutedEventArgs e ) {
        if ( !setupProgress && EocMonitor != null ) {
             EocMonitor.BackendWorker.ProgressChanged += BackendWorker_ProgressChanged;
             EocMonitor.BAckendWorker.RunWorkerCompleted += BackendWorker_RunWorkerCompleted;
             EocMonitor.EocWorker.ProgressChkanged += EocWorker_ProgresChanged;
             EocMonitor.EocWorker.RunWorkerCompleted += EocWorker_RunWorkerCompleted;
        }
    }

    private void BackendWorker_ProgressChanged( object sender, ProgressChangedEventArgs e ) {
        DiagnosticsInfo info = e.UserState as DiagnosticsInfo;

        // Other processing to notify the user of the progress
    }

    private void BackendWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
        // Processing to do when the back-ground worker is finished
    }

    private void DiagnosticsProgressCtrl_Click( object sender, RoutedEventArgs e ) {
        EocMonitor.BackendWorker.CancelAsync();
        EocMonitor.    EocWorker.CancelAsync();

        DiagnosticsProgressCtrl.Visibility = Visibility.Collapsed;

        e.Handled = true;
    }

    void EocWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
        // Processing to do when the back-ground worker is finished
    }

    private void RefreshButton_Click( object sender, RoutedEventArgs e ) {
        DiagnosticsProgressCtrl.Maximum = DiagnosticsProgressCtrl.Minimum = DiagnosticsProgressCtrl.Value = 0.0;

        DiagnosticsProgressCtrl.Visibility = Visibility.Visible;

        backendDataTypeCount   = eocDataTypeCount   = 0;
        backendWorkerCompleted = eocWorkerCompleted = false;

        EocMonitor.GetDiagnostics();

        e.Handled = true;
    }

}

問題は、DoWorkメソッドにブレークポイントを配置し、それらが完了するまで実行されるのを監視したにもかかわらず、RunWorkerCompletedメソッドが呼び出されていないことです。エラーが発生したり、スローされたりすることはありません。これは、EocMonitorクラスとDashboardクラスが2つの異なるDLLにあることです。それは違いを生みますか?私の知る限り、そうすべきではありませんが、完了したイベントハンドラーが呼び出されない理由がわかりません。BackgroundWorkersフロントエンドアプリケーションでをインスタンス化する必要がありますか?

トニー

4

2 に答える 2

2

イベントが発生しましたが、イベントに登録していなかったため、表示されませんRunWorkerCompleted...

BackendWorker.RunWorkerCompleted += BackendWorker_RunWorkerCompleted;
EocWorker.RunWorkerCompleted += EocWorker_RunWorkerCompleted;
于 2012-05-19T00:11:56.203 に答える
0

さて、上記を投稿した後、戻って少し変更しました。BackgroundWorkerここで、コントロール内のオブジェクトをインスタンス化し、DashboardそれらをEocMonitorのGetDiagnosticsメソッドに渡します。これらのオブジェクトを保持するEocMonitorのプロパティにはプライベートセッターがあるため、それらを使用する唯一の方法は、オブジェクトを作成してそのメソッドに渡すことです。のコードDashboard_Loadedはメソッド内で移動されRefreshButton_Click、オブジェクトがインスタンス化された後、オブジェクトがに渡される前に実行されます。GetDiagnostics.

これはすべて機能します!Progress_Changedメソッドとメソッドが実行されているのがわかりRunWorkerCompletedます。

おそらく機能しない理由がわかりました。EocMonitorオブジェクトは、プログラムの初期化フェーズ中にUI以外のスレッドで作成されます。UIオブジェクトのメソッドを呼び出すため、メソッドを呼び出せない可能性があります。ある種の無効な操作例外がスローされている可能性がありますが、それをキャッチする場所がありません。

それを教訓にしましょうBackgroundWorker。UIスレッドのコードでインスタンス化する必要があります。

于 2012-05-19T00:26:39.640 に答える