How to run a background process in response to selection change event in VSTO Office add-in?

给你一囗甜甜゛ 提交于 2019-12-24 02:51:11

问题


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?


回答1:


Suddenly all my other event handlers started erroring, saying "BeginInvoke cannot be called until the handle has been created".

That's curious. I'm also grasping at straws, but try this:

Control control = new Control();
IntPtr handle = control.Handle;

instead of calling SynchronizationContext.SetSynchronizationContext directly. You may need to do this at the beginning of each event.

(Idea taken from this blog entry).



来源:https://stackoverflow.com/questions/12898569/how-to-run-a-background-process-in-response-to-selection-change-event-in-vsto-of

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!