Question

I'm writing an extension that sometimes runs a fairly long batch job in the background, and needs to provide a reasonable indication to the user that it's actually working.

If possible, it would be nice to use the loading popup/ialog that VS2012 already uses, such as the "preparing solution" dialog. Does anyone know how to create an instance of that popup from an extension?

If not, are there any good alternatives? Being able to display a status string and progress bar would be preferable.

Was it helpful?

Solution

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);
      }
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top