Incorrect operation of async / wait, Excel events in Excel application level application

I had a problem using async / await in my add-in application, I have a custom task pane and the user can load some data with it, so problems arise:

  • After the expected operation completes, the control does not return to the previous execution context. I created an example with window forms and insert the same method with the wait, and it works fine - I can use the form controls after waiting, but not in the add-in, I need to call the custom taskbar Call the method, Simple example:

    private void SearchPaneButton_Click(object sender, EventArgs e) { Search(); } private async void Search() { var searchText = SearchTextBox.Text; SearchPaneButton.Text = "Loading…"; var data = await new DataServiceClient().GetDataAsync(searchText); this.Invoke((MethodInvoker)(() => { SearchPaneButton.Text = "Search"; ToggleWorkbookEvents(); })); } 
  • In my add-in, I need to handle some events - the worksheet is changed, the worksheet is activated / deactivated, but these events disappear and do not start after waiting, and I should use something like "switch" (delete + add) after each wait for use. A simple example:

     private void ToggleWorkbookEvents() { var excel = Globals.BPNAddIn.Application; //need to ensure event will not be set twice excel.SheetActivate -= CheckSheetForData; excel.SheetActivate += CheckSheetForData; if (excel.ActiveWorkbook != null) { var activeSheet = Globals.BPNAddIn.GetActiveWorksheet(); //need to ensure event will not be set twice activeSheet.Change -= Worksheet_Changed; activeSheet.Change += Worksheet_Changed; } } 

So, maybe the vsto framework cannot support the new features (e.g. async wait) from the latest versions of the .NET Framework?

+6
source share
1 answer

This is a longstanding issue with Office plugins: they do not provide a SynchronizationContext .

As I mentioned in my blog, you can get around this to make sure you have the correct SynchronizationContext . This is a bit hacky, but it works:

 private async void SearchPaneButton_Click(object sender, EventArgs e) { if (SynchronizationContext.Current == null) SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); await SearchAsync(); } private async Task SearchAsync() { var searchText = SearchTextBox.Text; SearchPaneButton.Text = "Loading…"; var data = await new DataServiceClient().GetDataAsync(searchText); SearchPaneButton.Text = "Search"; ToggleWorkbookEvents(); } 

Regarding the issue of event triggering, I have no idea.

+11
source

All Articles