I was looking for a way to display a progress dialog myself, and finally stumbled upon a class called CommonMessagePump
that provides the same waiting dialog that shows in Visual Studio when operations take a long time to complete.
It is a bit cumbersome to use, but it seems to work quite well. It does not display until your operation has taken two seconds or so, and it provides cancellation support as well.
Assuming you have a class called Item
and that it contains a property called Name
and you want to process a list of these items it can be done in something like the following way:
void MyLengthyOperation(IList<Item> items)
{
CommonMessagePump msgPump = new CommonMessagePump();
msgPump.AllowCancel = true;
msgPump.EnableRealProgress = true;
msgPump.WaitTitle = "Doing stuff..."
msgPump.WaitText = "Please wait while doing stuff.";
CancellationTokenSource cts = new CancellationTokenSource();
Task task = Task.Run(() =>
{
for (int i = 0; i < items.Count; i++)
{
cts.Token.ThrowIfCancellationRequested();
msgPump.CurrentStep = i + 1;
msgPump.ProgressText = String.Format("Processing Item {0}/{1}: {2}", i + 1, msgPump.TotalSteps, items[i].Name);
// Do lengthy stuff on item...
}
}, cts.Token);
var exitCode = msgPump.ModalWaitForHandles(((IAsyncResult)task).AsyncWaitHandle);
if (exitCode == CommonMessagePumpExitCode.UserCanceled || exitCode == CommonMessagePumpExitCode.ApplicationExit)
{
cts.Cancel();
msgPump = new CommonMessagePump();
msgPump.AllowCancel = false;
msgPump.EnableRealProgress = false;
// Wait for the async operation to actually cancel.
msgPump.ModalWaitForHandles(((IAsyncResult)task).AsyncWaitHandle);
}
if (!task.IsCanceled)
{
try
{
task.Wait();
}
catch (AggregateException aex)
{
MessageBox.Show(aex.InnerException.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}