continuousProgressWindow.ShowDialog(this);
backgroundWorker.RunWorkerAsync();
You've got a simple chicken-and-egg problem, you don't start the worker until after the dialog closes. ShowDialog() is a blocking call. So the RunWorkerCompleted event doesn't fire because the worker didn't get started. The simplest workaround is to swap the two statements:
backgroundWorker.RunWorkerAsync();
continuousProgressWindow.ShowDialog(this);
That is not entirely safe to do. Not a problem with this snippet but in real code there is a danger that the worker completes before the dialog is displayed. Low odds but not zero. To solve that, you want to delay the worker until you are sure the dialog is up and running. That can be done with an AutoResetEvent that is Set() by the dialog's OnShown() method. Or, more elegantly, by taking advantage of a trick:
this.BeginInvoke(new Action(() => backgroundWorker.RunWorkerAsync()));
continuousProgressWindow.ShowDialog(this);
The delegate target of Control.BeginInvoke() runs when the program re-enters the message loop. That happens after the dialog becomes visible :)