4

BackgroundWorker(プログレスバー付きのポップアップウィンドウ)を使用してWPF C#プロジェクトを作成しています。

プログラムをチェックするためにデバッグ(F5キー)を開始します。BackgroundWorkerが完了してポップアップウィンドウを閉じた後、を閉じてMainWindowもデバッグプロセスは自動的に停止しません。デバッグを停止するには、Shift+F5を手動で押す必要があります。

BackgroundWorkerスレッドは自動的に処理されるべきだと思いました。しかし、とにかく、私はまだ メソッドでbackgroundworker.Dispose()呼び出します。それでも、ポップアップウィンドウを閉じて、が完了すると、デバッグを停止するために手動でShift+F5を実行する必要があります。backgroundworker.CancelAsync()RunWorkerCompletedBackgroundWorker

プログラムがデバッグを自動的に停止しないようにするバックグラウンドで何が起こっていますか?どうすればわかりますか?

注:閉じる前に、backgroundworkerがDoWorkを終了し、完了していることを確認しました。ポップアップウィンドウとBackgroundWorkerを使用すると、メインウィンドウを閉じるとすぐにデバッグが自動的に停止します。

[コードで編集]

public partial class MainWindow : Window
{
    BackgroundWorker backgroundworker1 = new BackgroundWorker();

    PopUp pop1 = new PopUp();

public MainWindow()
{
    InitializeComponent();

    backgroundworker1.DoWork += BackgroundWorker_DoWork;
    backgroundworker1.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
    backgroundworker1.WorkerReportsProgress = true;
    backgroundworker1.ProgressChanged += BackgroundWorker_ProgressChanged;
    backgroundworker1.WorkerSupportsCancellation = true;
}

private void startBtn_Click(object sender, RoutedEventArgs e)
{
    pop1 = new PopUp();

    int iteration = 0;
    if (int.TryParse(iterationTb1.Text, out iteration))
    {
        pop1.Show();
        backgroundworker1.Dispose();
        backgroundworker1.RunWorkerAsync(iteration);
        outputTb1.Text = "running...";
    }
}

private void cancelBtn_Click(object sender, RoutedEventArgs e)
{
    pop1.Close();
    backgroundworker1.CancelAsync();
}

public static int DoSlowProcess(int iterations, BackgroundWorker worker, DoWorkEventArgs e)
{
    int result = 0;

    for (int i = 0; i <= iterations; i++)
    {
        if (worker != null)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return result;
            }
            if (worker.WorkerReportsProgress)
            {
                int percentComplete = (int)((float)i / (float)iterations * 100);
                worker.ReportProgress(percentComplete);
            }
        }

        Thread.Sleep(100);
        result = i;
    }

    return result;
}


private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var bgw = sender as BackgroundWorker;
    e.Result = DoSlowProcess((int)e.Argument, bgw, e);
}

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
    }
    else if (e.Cancelled)
    {
        outputTb1.Text = "Canceled";
    }
    else
    {
        outputTb1.Text = e.Result.ToString();
        backgroundworker1.CancelAsync();
        backgroundworker1.Dispose();
        pop1.Close();
        pop1.progressBar1.Value = 0;
    }
}

    private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pop1.progressBar1.Value = e.ProgressPercentage;
        pop1.progressLb1.Content = e.ProgressPercentage.ToString();
    }
}
4

1 に答える 1

3

OK、私はあなたの問題を再現することができ、また原因を見つけることができました。

この行を変更します。

// PopUp pop1 = new PopUp();  <-- this never-used Win was blocking your close-down.
PopUp pop1 = null;

あなたも持っているので

pop1 = new PopUp();
int iteration = 0;

varを初期化するためだけにオブジェクトを作成し、後でそれを上書きすることは、常にアンチパターンです。この場合、ウィンドウを作成しますが、Show()またはClose()を作成しないため、実際には有害です。

Backgroundworkerは関与していないことに注意してください。それはできませんでした、それはThreadPoolを使用し、それはバックグラウンドスレッドを意味します。問題なく実行されている複数のBackgroundworkerでアプリを閉じることができます。

于 2011-08-15T18:02:13.887 に答える