本文介绍了手动停机调试与BackgroundWorker的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写与使用的BackgroundWorker 的WPF C#项目(有进度条的弹出窗口)。



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



我觉得的BackgroundWorker 应自动照顾的线程。但无论如何,我还是叫 backgroundworker.Dispose() backgroundworker.CancelAsync() RunWorkerCompleted 方法。然而,在弹出窗口的关闭和完成的的BackgroundWorker ,我仍然需要手工做的 Shift + F5 以停止调试。



什么是在避免自动停止调试程序的后台怎么回事?
我怎么能找到?



请注意:我已经确定BackgroundWorker的完成DoWork的完成之前,我将其关闭。随着弹出窗口和BackgroundWorker的,它自动停止调试我关闭主窗口的那一刻。



 公共部分类主窗口:窗口
{
BackgroundWorker的backgroundworker1 =新的BackgroundWorker();

弹出式POP1 =新的弹出窗口();

公共主窗口()
{
的InitializeComponent();

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

私人无效startBtn_Click(对象发件人,RoutedEventArgs E)
{
POP1 =新的弹出窗口();

INT迭代= 0;
如果(int.TryParse(iterationTb1.Text,出迭代))
{
pop1.Show();
backgroundworker1.Dispose();
backgroundworker1.RunWorkerAsync(迭代);
outputTb1.Text =运行...;
}
}

私人无效cancelBtn_Click(对象发件人,RoutedEventArgs E)
{
pop1.Close();
backgroundworker1.CancelAsync();
}

公共静态INT DoSlowProcess(INT迭代,BackgroundWorker的工人,DoWorkEventArgs E)
{
INT结果= 0;

的for(int i = 0; I< =迭代;我++)
{
如果(!工人= NULL)
{
如果( worker.CancellationPending)
{
e.Cancel = TRUE;
返回结果;
}
如果(worker.WorkerReportsProgress)
{
INT PERCENTCOMPLETE =(INT)((浮点)I /(浮点)迭代* 100);
worker.ReportProgress(PERCENTCOMPLETE);
}
}

Thread.sleep代码(100);
结果= I;
}

返回结果;
}


私人无效BackgroundWorker_DoWork(对象发件人,DoWorkEventArgs E)
{
VAR BGW =发件人为BackgroundWorker的;
e.Result = DoSlowProcess((INT)e.Argument,BGW,E);
}

私人无效BackgroundWorker_RunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
{
如果(e.Error!= NULL)
{
MessageBox.Show(e.Error.Message);
}
,否则如果(e.Cancelled)
{
outputTb1.Text =取消;
}
,否则
{
outputTb1.Text = e.Result.ToString();
backgroundworker1.CancelAsync();
backgroundworker1.Dispose();
pop1.Close();
pop1.progressBar1.Value = 0;
}
}

私人无效BackgroundWorker_ProgressChanged(对象发件人,ProgressChangedEventArgs E)
{
pop1.progressBar1.Value = e.ProgressPercentage;
pop1.progressLb1.Content = e.ProgressPercentage.ToString();
}
}


解决方案

确定,我可以重现你的问题,也找到了症结



更改此行:

  //弹出式POP1 =新的弹出窗口(); <  - 这永远不会使用的运挡住你关机。 
弹出式POP1 = NULL;

由于您也有



  = POP1新的弹出窗口(); 
INT迭代= 0;



创建对象只是初始化一个变种,后来覆盖它始终是一个反模式。在这种情况下,因为你创建一个窗口,但从来没有显示()或关闭()它实际上是有害的。



请注意,该BackgroundWorker的不参与。它不可能是,它使用线程池,这意味着后台线程。您可以关闭应用程序与运行W / O问题的几个Backgroundworkers。


I am writing a WPF C# project with use of BackgroundWorker (a popup window with progress bar).

I start debugging (F5 key) to check my program. After the BackgroundWorker is completed and the popup window is closed, closing the MainWindow does not automatically stop the debugging process. I have to manually hit Shift+F5 to stop the debugging.

I thought BackgroundWorker should have taken care of the Thread automatically. But anyhow, I still call backgroundworker.Dispose() and backgroundworker.CancelAsync() in the RunWorkerCompleted method. And yet, on the closing of the popup window and completion of the BackgroundWorker, I still have to manually do a Shift+F5 to stop debugging.

What is going on in the background that avoid the program from stop debug automatically? How can I find out?

NOTE: I have made sure the backgroundworker is finished DoWork and completed before I close it. With the popup Window and the BackgroundWorker, it stop debugging automatically the moment I close the Main Window.

[EDIT with codes]

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();
    }
}
解决方案

OK, I could reproduce your problem and also found the cause.

Change this line:

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

Because you also have

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

Creating objects just to initialize a var and later overwriting it is always an anti-pattern. In this case it is actually harmful because you create a Window but never Show() or Close() it.

Note that the Backgroundworker is not involved. It couldn't be, it uses the ThreadPool and that means background Threads. You can close an App with several Backgroundworkers running w/o a problem.

这篇关于手动停机调试与BackgroundWorker的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 15:32