我有一个程序集在一个来自第三方的沙箱中的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线程中保持双工回调方法执行?
您正在使用AsyncOperationManager.SynchronizationContext
属性获取同步上下文。该物业使用引擎盖下的SynchronizationContext.Current
。
这意味着,获得的SynchronizationContext
取决于您访问该物业的环境:
正如你可以阅读in the docs:
默认实现是自由线程实现。
因此,如果未设置当前线程的同步上下文,您将获得默认的自由线程SynchronizationContext
实例。它将通过调用程序线程上的同步执行和Send
的Post
回调来进行ThreadPool
回调(因此“随机”工作线程会将它们接收)。
在Windows窗体应用程序中,主线程的SynchronizationContext
将初始化为WindowsFormsSynchronizationContext
实例。该实例将Post
回调到主UI线程。
在WPF应用程序中,这将是一个DispatcherSynchronizationContext
。
在控制台应用程序中,主线程将没有SynchronizationContext
。因此,我上面提到的自由线程选项开始了,所以你得到一个自由线程的SynchronizationContext
实例,发布到ThreadPool
。这几乎解释了你观察到的行为。
如果您需要同步,则可以为控制台应用程序的主线程实现自己的线程仿射SynchronizationContext
。但这并不容易。在控制台应用程序中,您没有消息循环,也没有可以管理回调队列的调度程序。你可以看看Stephen Cleary的这个great answer,了解异步SynchronizationContext
。您需要手动创建“主循环”。