STA 线程在 Winforms 中使用,但在作为控制台应用程序执行时不使用

STA thread used in Winforms but not when executed as a Console app

我有一个在第三方沙箱内的 STA 线程下运行的程序集,在这个线程中我创建了一个双工 WCF 客户端,它需要在原始 STA 线程上执行方法。

当前的实现工作正常,在 Duplex 回调中,我按如下方式获取 STA 线程的同步上下文,并将其用于 Post 返回 STA 线程:

private readonly SynchronizationContext _syncContext = AsyncOperationManager.SynchronizationContext;

这一切都在 STA 线程中初始化的 WinForm 中运行,很好...但是我需要移动 WCF 双工代理,以便它在主 STA 线程中的 class 实例下运行。当我删除 winform 时,我最终从上面的 SynchronizationContext 获得了一个全新的线程。

澄清一下:

Winforms:-

没有 WinForm(class 实例):-

在线程 11 而不是 1 上执行意味着我的方法无法在沙箱内正确执行,除了在 winform 下运行的变体之外,变体之间的代码没有区别。有谁知道我如何在不使用 winform 的情况下在主 STA 线程中保持双工回调方法的执行?

您正在使用 AsyncOperationManager.SynchronizationContext 属性 获取同步上下文。 属性 在后台使用 SynchronizationContext.Current

也就是说,得到的SynchronizationContext取决于你访问属性的环境:

  • 您正在访问 属性 的线程,并且
  • 应用程序的类型。

如你所见in the docs:

The default implementation is the free-threaded implementation.

因此,如果未设置当前线程的同步上下文,您将获得一个默认的自由线程 SynchronizationContext 实例。它将 Send 通过在调用者线程上同步执行的回调和 PostThreadPool 的回调(因此 "random" 工作线程将接收它们)。

在 Windows 表单应用程序中,主线程的 SynchronizationContext 将为您初始化为 WindowsFormsSynchronizationContext 实例。该实例将 Post 回调到主 UI 线程。

在 WPF 应用程序中,这将是 DispatcherSynchronizationContext

在控制台应用程序中,主线程不会有 SynchronizationContext。因此,我上面提到的自由线程选项启动了,所以你得到了一个自由线程 SynchronizationContext 实例,它发布到 ThreadPool。这几乎可以解释您观察到的行为。

如果您需要同步,您可以为控制台应用程序的主线程实现自己的线程仿射 SynchronizationContext。但这并不容易。在控制台应用程序中,您没有消息循环,也没有可以管理回调队列的调度程序。您可以查看 Stephen Cleary 的 以了解异步 SynchronizationContext 的想法。不过,您需要手动创建 'main loop'。