Excel异步/等待工作不正确,Excel应用程序级外接程序中的Excel事件

Max*_*nev 9 c# excel vsto add-in async-await

我在加载项应用程序中使用async/await遇到问题,我有自定义任务窗格,用户可以用它下载一些数据,所以有问题:

  1. 等待操作完成后,控件不会返回到先前的执行上下文.我用windows窗体创建了一个示例并粘贴了相同的方法等待它工作正常 - 我可以在等待操作后使用表单控件,但不是在加载项中,我必须调用自定义任务窗格调用方法.简单的例子:

    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();
        }));
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在我的加载项中,我需要处理一些事件 - 工作表已更改,工作表已激活/已停用,但这些事件消失,并且在等待操作后未触发,我必须在每次事件后使用"切换"(删除+添加)事件等待使用.简单的例子:

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

那么也许vsto框架不能支持最新版本.NET Framework的新功能(如异步等待)?

Ste*_*ary 16

这是Office插件的一个长期问题:它们没有提供SynchronizationContext.

正如我在博客中提到的那样,你可以通过确保你有一个合适的方法SynchronizationContext解决这个问题.这有点hacky,但它的工作原理:

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();
}
Run Code Online (Sandbox Code Playgroud)

就"切换事件"问题而言,我不知道.

  • @JeremyThompson:因为你的代码必须做一些事情,框架*不应该只是在这里,而是在任何地方调用你的代码.:/ (2认同)