gpt4 book ai didi

c# - ExcelDNA : Async: The calling thread must be STA

转载 作者:太空宇宙 更新时间:2023-11-03 19:52:58 25 4
gpt4 key购买 nike

我正在使用 ExcelDna 和异步函数。如果 async:d 代码中存在异常,我想显示一个精美的 WPF 错误窗口。我的问题是出现错误“调用线程必须是 STA,因为许多 UI 组件都需要这个。”我该如何解决这个问题?

    [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 机制将在 await 之后运行代码(包括您的 catch 处理程序) ThreadPool线程。这不是您可以直接显示 WPF 表单的上下文。

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

更好的做法可能是假设 catch 处理程序在 ThreadPool 线程上运行,并从 catch 处理程序调用 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 以在主线程上运行“显示”。

C# async/await 机制不太适用于 Excel,因为 native /托管转换以及 Excel 在内部执行的任何操作都会弄乱需要在延续之间流动的线程上下文。即使在 .NET 方面,也不清楚如何在 AppDomain(不同的 Excel 加载项)之间管理线程上下文。因此,最好不要依赖 .NET 运行时能够通过托管/ native 转换对任何类型的上下文进行线程化。

关于c# - ExcelDNA : Async: The calling thread must be STA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36485658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com