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 (开发者_StackOverflow中文版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.
精彩评论