I have an VSTO application-level add-in, with my own custom task pane. I’m trying to intercept the SelectionChange event, and display information in my custom task pane that’s relevant to the selection. I do know how to do that synchronously.
However the process of fetching the information to display is slow, and I don’t want to block the application while I fetch the information. Furthermore, the user may change the selection several times, and I want to cancel any in-progress “fetch” operation if this happens.
I’ve tried await-ing the long-running operation, but since I don’t have a form open, there is no synchronization context in place, hence I get an InvalidOperationException (cross-thread operation not valid) as soon as I try to update the controls on my task pane.
async void Application_WindowSelectionChange(PowerPoint.Selection selection)
{
var results = await MyLongRunningOperation(cancellationTokenSource.Token);
myControl.Text = DescribeResults(results); // BOOM!
}
What’s the best way to overcome this? I tried doing as Stephen suggested in the link above, by putting the following at the start of the selection-changed event handler:
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext())
That didn’t work. Suddenly all my other event handlers started erroring, saying “BeginInvoke cannot be called until the handle has been created”. I tried putting the same code at the start of every event handler, in case it was an all-or-nothing deal. That didn’t work either. Perhaps I should have created one WindowsFormsSynchronizationContext object and used it for all the handlers – but I’m aware I’m now clutching at straws.
If that doesn’t work, what other approaches should I try? Is BeginInvoke still the way to go, or can I jump over to the UI thread some other way?
That’s curious. I’m also grasping at straws, but try this:
instead of calling
SynchronizationContext.SetSynchronizationContextdirectly. You may need to do this at the beginning of each event.(Idea taken from this blog entry).