【问题标题】:Manual stop debugging with backgroundworker使用后台工作程序手动停止调试
【发布时间】:2011-08-14 11:39:39
【问题描述】:

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

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

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

后台发生了什么导致程序无法自动停止调试? 我怎样才能知道?

注意:我已确保后台工作程序已完成 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();
    }
}

【问题讨论】:

  • 有些东西让你的进程保持活力,它可能不是 bgw。
  • 虽然我是这样,但是当我没有后台工作人员时,它会自动停止调试。我怎样才能知道?
  • 我同意 Henk 的观点,可能不是后台工作人员。当调试器处于这种状态时,您能否执行“Break All”并使用“线程”窗口查看每个线程在做什么?
  • 我做了一个“Break All”,它只显示在 VS2010“No Source Available”中。我找不到调用“线程”的窗口,有“IntelliTrace”和“输出”窗口,但它们没有任何有用的建议。
  • 要到达任何地方,请发布与显示弹出窗口和关闭相关的所有代码。

标签: c# wpf backgroundworker visual-studio-debugging


【解决方案1】:

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

改变这一行:

// 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。不可能,它使用线程池,这意味着后台线程。您可以关闭一个应用程序,其中有多个后台工作人员正在运行而没有问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    相关资源
    最近更新 更多