0

私のアプリケーションには、テーブルをいっぱいにしてログ メッセージを送信する 2 つのバックグラウンド ワーカーがあります。これらのデータは、ReportProgress メソッドの「userState」を使用して送信されます。
これらは、次の方法でメイン スレッドに接続されます。

msg_worker.DoWork              += message_worker_task;
msg_worker.ProgressChanged     += msg_worker_ProgressChanged;
msg_worker.RunWorkerCompleted  += worker_completed;

data_worker.DoWork             += data_worker_task;
data_worker.ProgressChanged    += data_worker_ProgressChanged;
data_worker.RunWorkerCompleted += worker_completed;

これらは、doWork タスクの最後に設定された 2 つの EventWaitHandle アイテムを使用して同期されます。

private void message_worker_task(object sender, DoWorkEventArgs e)
    {
        try
        {
            while( .. ){ 
               // do work
               bw.ReportProgress( 10, new String("my message to append"));
            }
        }
        finally
        {
            e.Result = 0;
            msg_done.Set(); // EventWaitHandle
        }
    }

Progress changed デリゲートは、ユーザーに表示されるコンポーネントにデータ/ログを挿入します。

さて、問題は、UI の [Quit] ボタンをクリックすると、次のように 2 つのスレッドを待機することです。

private void wait_threads()
    {
        int timeout = 30000;
        Cursor.Current = Cursors.WaitCursor;
        if (data_worker.IsBusy && !data_worker.CancellationPending)
        {
            data_worker.CancelAsync();
            data_done.WaitOne(timeout);
        }
        if (msg_worker.IsBusy && !msg_worker.CancellationPending)
        {
            msg_worker.CancelAsync();
            msg_done.WaitOne(timeout);
        }
        Cursor.Current = Cursors.Default;
    }

これは機能しているように見えますが (コードの他の場所で使用しています)、この「終了」の場合、ログ コンポーネントにデータを挿入しようとしたという例外が発生しました。このコンポーネントは、RunWorkerCompleted デリゲートによって操作されます。

Quit がクリックされたときに実行されるコードは次のとおりです。

    private void quit_Click(object sender, EventArgs e)
    {
        wait_threads(); // blocks until threads are finished
        Close();
    }

スレッドが完了するのを待っている間に、最後のイベントである RunWorkerCompleted を送信することがわかったと思います。問題は、私が自分のフォームを Close() している最中であることです。これは、フォームが正しい状態にないことを意味します。さらに、関数e.Cancelled内のフラグを確認するworker_completedと、false と表示されます...

関数が実行される前にRunWorkerCompletedが確実に処理されるようにするにはどうすればよいですか? Close()(または、終了しているため、まったく処理されません)。

4

1 に答える 1

0

ReportProgress を呼び出す前に、Cancellation Pending プロパティを確認できると思います。

while( .. ){ 
    if (!bw.CancellationPending) 
              bw.ReportProgress( 10, new String("my message to append"));
}
于 2013-04-17T10:24:55.917 に答える