-2

これは私を困惑させました。ソフトウェアのエンタープライズ インストールを支援するために作成した単純なユーティリティがあります。1 つのコンポーネントは、ユーザーが現在自分のマシンに持っている AppData ファイルをバックアップし、デスクトップ上のフォルダーに保存します。

private void backupButton_Click(object sender, EventArgs e)
{
    backgroundBackup.RunWorkerAsync();
}


private void backgroundBackup_DoWork(object sender, DoWorkEventArgs e)
{
    ...
}

private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
    ...
}

// I removed the message boxes from DoWork, and added a RunWorkerCompleted event, 
// but neither the confirmation nor the error messgae box from RunWorkerCompleted are shown.

private void backgroundBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    ...
}

これは機能しますが、期待した結果が得られません。各ユーザーがバックアップするファイルの合計サイズが 1 ~ 2 GB に近づく可能性があるため、この操作をバックグラウンド スレッドに置きました。これを実行するたびに、ターゲットからすべてのファイルとフォルダーではなく一部がコピー先にコピーされ、コピーされるフォルダーは毎回異なります。少数のファイルとフォルダーのみがコピーされる場合もあれば、ほとんどすべてがコピーされる場合もありますが、ターゲット全体がコピーされることはありません。この操作を単純なコンソール アプリに配置すると、毎回機能します。DoWork メソッドですべての作業を行わない原因となっている BackgroundWorker クラスについて理解する必要があることはありますか?

編集:

BackgroundWorker クラスの問題を複雑にしすぎているのではないかと思います。同僚と話をしたところ、潜在的に長いプロセスを処理するために新しいスレッドを作成する簡単な方法が提案されました。

    private void backupButton_Click(object sender, EventArgs e)
    {
        Thread backupThread = new Thread(backupThreadJob);
        backupThread.Start();      
    }

    private void backupThreadJob()
    {
        try
        {
            //copy files and stuff
        }

        catch(Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
        }
    }

これで仕事は完了です。私は BackgroundWorker を使用しようとして失敗し、一部のファイルのみがコピーされている理由を理解できませんでした。みんなの助けに感謝します!

4

2 に答える 2

4

これは完全な答えではありません。しかし、次のことが問題と関係があると想像できます。

は別の非 UI スレッドでメソッドをBackgroundWorker実行するため、そこで呼び出すことはお勧めできません。UI (「フォアグラウンド」) スレッドで実行している場合にのみ、UI の処理を​​行う必要があります。DoWorkMessageBox.Show

DoWork イベント ハンドラーでユーザー インターフェイス オブジェクトを操作しないように注意する必要があります。代わりに、ProgressChanged および RunWorkerCompleted イベントを介してユーザー インターフェイスと通信します。クラスの MSDN リファレンス ページBackgroundWorker

メソッドのどこかで例外が発生し、catchブロックにメッセージボックスを表示したい場合、この呼び出しはさらに別の例外をトリガーし、処理されません...したがって、メソッドは途中で中止されます。

于 2012-05-20T18:03:24.943 に答える
1

これは、バックグラウンドスレッドからメッセージボックスを呼び出すことができることを示す例です。MessageBox.Showは静的メソッド呼び出しであり、バックグラウンドスレッドから呼び出すことができます。UIレイヤー上の何かにアクセスしようとしないでください(バインドされたバッキングオブジェクトを含む-ここでWPFを考えてください)。

これがメッセージボックスに使用される場所の例です。

10個のファイルをコピーしたいのですが、バックグラウンドでコピープロセスを開始します。エラーが発生し(ファイルが存在するなど)、ユーザーに上書きを促す必要があります。ユーザーに確認を求めるメッセージボックスを表示できます。

private void button1_Click(object sender, EventArgs e)
{
    BackgroundWorker bw = new BackgroundWorker();
    bw.RunWorkerCompleted += BwOnRunWorkerCompleted;
    bw.DoWork += BwOnDoWork;
    bw.RunWorkerAsync();
}

private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
    MessageBox.Show("This is a message from a background thread");
}

private void BwOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
    MessageBox.Show("Your done");
}
于 2012-05-20T19:25:18.280 に答える