Search code examples
outlookvstointeropoutlook-addinoffice-addins

VSTO Outlook: How to perform a long task without blocking the Outlook main UI thread


When the "To" field losew the focus from the compose window I need to perform a long task which takes some time to be completed. Now UI is getting blocked because I do it in the main UI thread so I would like to make it non-blocking. I have thought in using the async/await commands from C# as below:

public async void PerformLongTask()
{
   bool result = await Task.Run(() =>
         {
                // Long task here
         });
}

I would like to know if this is the correct way to do an asynchronous task without blocking the main UI thread in Outlook or is there some other better way to do it? If so, how? When you need to perform such long task and you need to be non-blocking, how do you usually do it?


Solution

  • async/await or tasks are fine in Outlook as long as you don't touch any Outlook Object Model objects on that secondary thread.

    If you need to touch OOM objects, do so by switching to the main thread using, for example, the Dispatcher object - retrieve it on the main thread from Dispatcher.CurrentDispatcher, then using Dispatcher.Invoke/InvokeAsync whenever you need to do anything with Outlook objects. Since thread switching is expensive, try to batch multiple OOM hits into a single Invoke.

    public async void PerformLongTask()
    {
       var dispatcher = Dispatcher.CurrentDispatcher;
       bool result = await Task.Run(() =>
             {
                    // Long task here
                    //now use OOM on the main thread
                    dispatcher.Invoke(() =>
                    {
                       MessageBox.Show(Globals.ThisAddIn.Application.Version);
                    }); 
             });
    }