WCF Named Pipes timeout in a WinApp, but not in a ConsoleApp?

瘦欲@ 提交于 2020-01-17 08:35:13

问题


In relation to Async two-way communication with Windows Named Pipes (.Net) which seems dead (the thread that is) :/

I'm wondering why the following code works perfectly in a ConsoleApplications, but when I do exactly the same thing with WindowsApplications I get an timeout on the client when calling "Console.WriteLine(proxy.ProcessData());". The strange thing is that the server method "ProcessData" is called without any exceptions, but still I get a timeout after the default 1 min?!

How can I fix this... and what exactly is the difference between between and ConsoleApp and a WinApp (besides the obvious) which is the reason something like this doesn't work?

Using WCF you can use duplex named pipes

// 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();
    }

Implement the Service

[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();
        }
    }

Host the Service

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();
        }
    }
}

Create the client application, in this example the Client class implements the call back contract.

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");
    }
}

回答1:


The reason is synchronization context that is important when callback is called. You call callback method from inside ProcessData.

In case of console application there is no any synchronization context set, which means that WCF will call callback method on the client in the separate thread while main thread is waiting when ProcessData returns. You can see this if you log thread ID in your console messages.

In case of Windows application main thread sets synchronization context (either WinForms or WPF). If you call your service from main thread, then WCF will try to call your callback method in the same synchronization context. But the only thread of this synchronization context is busy with waiting for ProcessData to return.

You can solve that by two means: 1. Set UseSynchronizationContext=false for your callback. 2. Call your service from background thread of the application - then callback will be called on some other threadpool thread.

Be aware that with both options you can't access UI elements from these background threads directly - you'll need to marshal calls to UI thread.



来源:https://stackoverflow.com/questions/43013991/wcf-named-pipes-timeout-in-a-winapp-but-not-in-a-consoleapp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!