繁体   English   中英

ExcelDna:异步:调用线程必须是STA

[英]ExcelDna: Async: The calling thread must be STA

我正在使用ExcelDna和异步功能。 如果async:d代码中有异常,我想显示一个奇特的WPF错误窗口。 我的问题是,我收到错误消息“调用线程必须是STA,因为许多UI组件都需要STA。” 我该如何解决?

    [ExcelFunction(Description = "", Category = "")]
    public static async Task<object> /*string*/ Foo(CancellationToken ct)
    {
        try
        {
            return await Task.Run(async () =>
            {
                await Task.Delay(1000, ct);
                throw new Exception("BOO");
                return "HelloWorld";
            }, ct2.Token);
        }
        catch (Exception e)
        {
            return ShowWpfErrorWindowThatRequiresSTA(e);
        }
    }

当您的Excel函数运行时,没有安装SynchronizationContext.Current ,因此async / await机制将在ThreadPool线程上的await (包括您的catch处理程序)之后运行代码。 那不是您可以直接显示WPF表单的上下文。

安装与在主线程(或另一个线程)上运行的Dispatcher相对应的DispatcherSynchronizationContext是可行的,但是您必须为每个UDF调用执行此操作。 通过Excel的本机代码路径以某种方式丢失了主线程上的.NET调用上下文,因此SynchronizationContext丢失了。

最好假设捕获处理程序正在ThreadPool线程上运行,并从捕获处理程序进行SynchronizationContext.Post调用,以使您回到运行Dispatcher和WPF表单的主线程。

您可以查看Excel-DNA如何实现(WinForms)LogDisplay窗口。 https://github.com/Excel-DNA/ExcelDna/blob/master/Source/ExcelDna.Integration/LogDisplay.cs )。 您可以从任何线程调用LogDisplay.WriteLine(...) ,它将执行_syncContext.Post以在主线程上运行“ Show”。

C#异步/等待机制在Excel中的效果较差,因为本机/托管的转换以及Excel在内部所做的任何事情都弄乱了需要在延续之间流动的线程上下文。 即使在.NET方面,也不清楚如何在AppDomain(不同的Excel加载项)之间管理线程上下文。 因此,最好不要依赖.NET运行时能够通过托管/本机转换线程化任何类型的上下文。

许多Office插件都有一个问题,其中SynchronizationContext.Currentnull ,并且异步继续在线程池上执行。 我将在第一次await之前检查SynchronizationContext.Current的值。

我曾在创造一些成功WinFormsSynchronizationContext和第一,然后再安装该线程上await 但是,安装WPF上下文会更加复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM