我有一个程序集,该程序集在第三方的沙箱中的STA线程下运行,在该线程中,我创建了一个双工WCF客户端,该客户端需要在原始STA线程上执行方法。
当前的实现工作正常,在Duplex回调中,我按如下方式获取STA线程的同步上下文,并将其用于回发到STA线程:
private readonly SynchronizationContext _syncContext = AsyncOperationManager.SynchronizationContext;
所有这些都在STA线程中初始化的WinForm中运行,太好了...但是我需要移动WCF双工代理,因此它可以在主STA线程中的类实例下运行。当我删除winform时,我最终从上述SynchronizationContext中获得了一个全新的线程。
要澄清:
Winforms:-
没有WinForm(类实例):-
在线程11而不是1上执行意味着我的方法无法在沙箱中正确执行,除了在Winform下运行之外,变量之间的代码没有区别。有谁知道我如何在不使用winform的情况下保持STA主线程中双工回调方法的执行?
答案 0 :(得分:5)
您正在使用AsyncOperationManager.SynchronizationContext
属性获取同步上下文。该属性在内部使用SynchronizationContext.Current
。
这意味着,获得的SynchronizationContext
取决于您在以下位置访问属性的环境:
您可以阅读in the docs:
默认实现是自由线程实现。
因此,如果未设置当前线程的同步上下文,则将获得默认的自由线程SynchronizationContext
实例。它将通过在调用者线程上同步执行而Send
个回调,以及对Post
的{{1}}个回调(因此,“随机”工作线程会选择它们)。
在Windows Forms应用程序中,主线程的ThreadPool
将为您初始化为SynchronizationContext
实例。该实例将WindowsFormsSynchronizationContext
回调到主UI线程。
在WPF应用中,这将是Post
。
在控制台应用程序中,主线程没有DispatcherSynchronizationContext
。因此,我上面提到的自由线程选项开始执行,因此您获得了一个发布到SynchronizationContext
的自由线程SynchronizationContext
实例。几乎可以解释您观察到的行为。
如果需要同步,则可以为控制台应用程序的主线程实现自己的线程仿射ThreadPool
。不过,这并不容易。在控制台应用程序中,您没有消息循环,也没有可以管理回调队列的调度程序。您可以查看Stephen Cleary的great answer,了解异步SynchronizationContext
的概念。不过,您将需要手动创建“主循环”。