4

我正在使用BackgroundWorker(带有进度条的弹出窗口)编写一个 WPF C# 项目。

我开始调试(F5 键)来检查我的程序。完成BackgroundWorker并关闭弹出窗口后,关闭MainWindow并不会自动停止调试过程。我必须手动按Shift+F5来停止调试。

我认为BackgroundWorker应该自动处理线程。但无论如何,我还是调用 了backgroundworker.Dispose()and方法。然而,在弹出窗口关闭并完成后,我仍然需要手动执行Shift+F5来停止调试。backgroundworker.CancelAsync()RunWorkerCompletedBackgroundWorker

后台发生了什么避免程序自动停止调试?我怎样才能知道?

注意:我已确保后台工作人员已完成 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

好的,我可以重现您的问题并找到原因。

更改此行:

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

因为你也有

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

创建对象只是为了初始化一个 var 然后覆盖它总是一种反模式。在这种情况下,它实际上是有害的,因为您创建了一个 Window 但从来没有 Show() 或 Close() 它。

请注意,不涉及 Backgroundworker。不可能,它使用线程池,这意味着后台线程。您可以关闭一个应用程序,其中有多个运行 w/oa 问题的 Backgroundworkers。

于 2011-08-15T18:02:13.887 回答