Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# STA线程在Winforms中使用,但在作为控制台应用程序执行时不使用_C#_Multithreading_Winforms_Wcf_Callback - Fatal编程技术网

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

C# STA线程在Winforms中使用,但在作为控制台应用程序执行时不使用,c#,multithreading,winforms,wcf,callback,C#,Multithreading,Winforms,Wcf,Callback,我有一个在来自第三方的沙箱中的STA线程下运行的程序集,在这个线程中,我创建了一个需要在原始STA线程上执行方法的双工WCF客户端 当前实现工作正常,在双工回调中,我获得STA线程的同步上下文,如下所示,并使用它发回STA线程: private readonly SynchronizationContext _syncContext = AsyncOperationManager.SynchronizationContext; 这一切都在STA线程中初始化的WinForm中运行,很好……但我需

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

当前实现工作正常,在双工回调中,我获得STA线程的同步上下文,如下所示,并使用它发回STA线程:

private readonly SynchronizationContext _syncContext = AsyncOperationManager.SynchronizationContext;
这一切都在STA线程中初始化的WinForm中运行,很好……但我需要移动WCF双工代理,使其在主STA线程中的类实例下运行。当我删除winform时,我最终从上面的SynchronizationContext中得到了一个全新的线程

澄清:

Winforms:-

在STA线程上启动WCF双工代理-ManagedThreadId=1 从服务器接收双工回调-ManagedThreadId=5 使用AsyncOperationManager.SynchronizationContext-ManagedThreadId=1发布到回调事件方法 没有WinForm类实例:-

在STA线程上启动WCF双工代理-ManagedThreadId=1 从服务器接收双工回调-ManagedThreadId=6 使用AsyncOperationManager.SynchronizationContext-ManagedThreadId=11发布到回调事件方法
在线程11而不是1上执行意味着我的方法无法在沙箱中正确执行,除了在winform下运行的变量外,变量之间的代码没有区别。有人知道如何在不使用winform的情况下在主STA线程中保持双工回调方法的执行吗?

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

这意味着,获得的SynchronizationContext取决于您在其中访问属性的环境:

正在访问其属性的线程,以及 应用程序的类型。 正如你所看到的:

默认实现是自由线程实现

因此,如果未设置当前线程的同步上下文,您将获得一个默认的免费线程同步上下文实例。它将通过在调用线程上同步执行来发送回调,并将回调后发到线程池,以便随机工作线程将其拾取

在Windows窗体应用程序中,主线程的SynchronizationContext将为您初始化为WindowsFormsSynchronizationContext实例。该实例将回调发布到主UI线程

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

在控制台应用程序中,主线程将没有SynchronizationContext。因此,我上面提到的自由线程选项起作用了,因此您将获得一个自由线程同步上下文实例,该实例将发布到线程池。这很好地解释了你观察到的行为


如果需要同步,可以为console应用程序的主线程实现自己的线程仿射同步上下文。但这并不容易。在控制台应用程序中,您没有消息循环,也没有可以管理回调队列的调度程序。您可以看看Stephen Cleary的文章,了解异步同步上下文的概念。但是,您需要手动创建“主循环”。

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

这意味着,获得的SynchronizationContext取决于您在其中访问属性的环境:

正在访问其属性的线程,以及 应用程序的类型。 正如你所看到的:

默认实现是自由线程实现

因此,如果未设置当前线程的同步上下文,您将获得一个默认的免费线程同步上下文实例。它将通过在调用线程上同步执行来发送回调,并将回调后发到线程池,以便随机工作线程将其拾取

在Windows窗体应用程序中,主线程的SynchronizationContext将为您初始化为WindowsFormsSynchronizationContext实例。该实例将回调发布到主UI线程

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

在控制台应用程序中,主线程将没有SynchronizationContext。因此,我上面提到的自由线程选项起作用了,因此您将获得一个自由线程同步上下文实例,该实例将发布到线程池。这很好地解释了你观察到的行为

如果需要同步,可以为console应用程序的主线程实现自己的线程仿射同步上下文。但这并不容易。在控制台应用程序中,您没有消息循环,也没有可以管理回调队列的调度程序。你可以看看Stephen Cleary的这篇文章,了解as的概念
同步同步上下文。不过,您需要手动创建一个“主循环”。

您能发布您的主方法吗?如果没有它,下面的诊断就是假设。你的标题说运行作为一个控制台应用程序,这有两个潜在的来源。第一个问题是你是否用[StatThread]装饰主方法?第二个也是更可能的问题是控制台应用程序没有安装基于线程类型的同步上下文;创建上下文时,它是SynchronizationContext类的一个实例,它使用线程池。为什么首先需要STA?是否涉及COM对象?你能在控制台应用程序中使用甚至不可见的表单吗?如果是,您可以使用此表单的同步上下文。您可以发布您的主要方法吗?如果没有它,下面的诊断就是假设。你的标题说运行作为一个控制台应用程序,这有两个潜在的来源。第一个问题是你是否用[StatThread]装饰主方法?第二个也是更可能的问题是控制台应用程序没有安装基于线程类型的同步上下文;创建上下文时,它是SynchronizationContext类的一个实例,它使用线程池。为什么首先需要STA?是否涉及COM对象?你能在控制台应用程序中使用甚至不可见的表单吗?如果是,您可以使用此表单的同步上下文。