WCF 命名管道在 WinApp 中超时,但在控制台应用中没有?



关于与Windows命名管道(.Net)的异步双向通信,这似乎已经死了(线程是):/

我想知道为什么以下代码在控制台应用程序中完美运行,但是当我对Windows应用程序执行完全相同的操作时,在调用"Console.WriteLine(proxy.进程数据());"。奇怪的是,服务器方法"ProcessData"被调用而没有任何异常,但我在默认的 1 分钟后仍然超时?!

我该如何解决这个问题...ConsoleApp 和 WinApp 之间到底有什么区别(除了显而易见的),这就是这样的东西不起作用的原因?

使用 WCF,可以使用双工命名管道

// Create a contract that can be used as a callback
public interface IMyCallbackService
{
[OperationContract(IsOneWay = true)]
void NotifyClient();
}
// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
[OperationContract]
string ProcessData();
}

实施服务

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
public string ProcessData()
{
// Get a handle to the call back channel
var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();
callback.NotifyClient();
return DateTime.Now.ToString();
}
}

托管服务

class Server
{
static void Main(string[] args)
{
// Create a service host with an named pipe endpoint
using (var host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
{
host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
host.Open();
Console.WriteLine("Simple Service Running...");
Console.ReadLine();
host.Close();
}
}
}

创建客户端应用程序,在此示例中,客户端类实现回调协定。

class Client : IMyCallbackService
{
static void Main(string[] args)
{
new Client().Run();
}
public void Run()
{
// Consume the service
var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.ProcessData());
}
public void NotifyClient()
{
Console.WriteLine("Notification from Server");
}
}

原因是调用回调时很重要的同步上下文。 从ProcessData内部调用回调方法。

对于控制台应用程序,没有任何同步上下文集,这意味着 WCF 将在主线程等待ProcessData返回时在单独的线程中调用客户端上的回调方法。如果您在控制台消息中记录线程 ID,则可以看到此信息。

在Windows应用程序主线程设置同步上下文(WinForms或WPF)的情况下。如果从主线程调用服务,则 WCF 将尝试在同一同步上下文中调用回调方法。但是此同步上下文的唯一线程忙于等待ProcessData返回。

您可以通过两种方式解决此问题: 1. 设置回拨UseSynchronizationContext=false。 2. 从应用程序的后台线程调用您的服务 - 然后回调将在其他线程池线程上调用。

请注意,使用这两个选项时,您无法直接从这些后台线程访问 UI 元素 - 您需要封送对 UI 线程的调用。

相关内容

最新更新