I've made a small app where Form
is threaded (using BackgroundWorker
), and in the form I'm calling a function QuitApplication
in Program
class when I want to quit.
The DoWork
looks like this:
static void guiThread_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
if (worker.C开发者_StackOverflow中文版ancellationPending == true)
{
e.Cancel = true;
break;
}
if (Program.instance.form != null)
{
Program.instance.form.UpdateStatus(Program.instance.statusText, Program.instance.statusProgress);
}
Thread.Sleep(GUI_THREAD_UPDATE_TIME);
}
}
and in the Form1 class i have this method attached to the closing of the window:
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Program.instance.SetStatus("Closing down...", 0);
Program.QuitApplication();
}
So what i want is to ensure that everything quits when I press the X on the window. However, the if( worker.CancellationPending == true )
never hits... why is this?
QuitApplication looks like this:
public static void QuitApplication()
{
Program.instance.guiThread.CancelAsync();
Application.Exit();
}
And Im using guiThread.WorkerSupportsCancellation = true
CancelAsync
is setting the CancellationPending
property, but then you immediately quit the application without giving the background thread a chance to detect that and shut down. You need to change your UI code to wait for the background thread to finish.
Personally, when I write apps like this, I make the form close button act like a Cancel button rather than quit immediately. It's a lot safer for the end user. For example:
private void abortButton_Click(object sender, EventArgs e) {
// I would normally prompt the user here for safety.
worker.CancelAsync();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if(worker.IsBusy) {
// If we are still processing, it's not very friendly to suddenly abort without warning.
// Convert it into a polite request instead.
abortButton.PerformClick();
e.Cancel = true;
}
}
精彩评论