不正确的asynchronous/等待工作,Excel应用程序级别加载项中的Excel事件
我在加载项应用程序中遇到了使用asynchronous/等待的问题,我有自定义任务窗格,用户可以使用它下载一些数据,所以出现问题:
-
待完成的操作完成后,控件不会返回到上一个执行上下文。 我用windows窗体创build了示例,并粘贴与等待相同的方法,它工作正常 – 我可以在等待操作后使用窗体控件,但不是在加载中,我不得不调用自定义任务窗格调用方法。 简单的例子:
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(); })); }
-
在我的插件中,我需要处理一些事件 – 工作表被改变,工作表被激活/停用,但是这些事件消失并且在等待操作之后不被触发,并且我必须在每个事件之后使用诸如“切换”(移除+添加)事件等待使用。 简单的例子:
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; } }
所以也许vsto框架不能支持最新版本的.NET Framework的新function(如asynchronous等待)?
这是Office插件长期存在的问题:它们不提供SynchronizationContext
。
正如我在我的博客中提到的,您可以通过确保您具有适当的SynchronizationContext
来解决此问题。 这有点哈克,但它的作品:
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(); }
至于“切换事件”的问题,我不知道。