Getting a PipeException (pipe is closing) with a WCF service that uses NamedPipesBinding

lysergic-acid picture lysergic-acid · Aug 13, 2012 · Viewed 9.3k times · Source

I am just learning WCF, trying out different things.

I have set up the following service:

[ServiceBehavior(IncludeExceptionDetailInFaults = true , 
    InstanceContextMode = InstanceContextMode.Single)]
    public class TestService : ITestService
    {
        // This operation is defined as OneWay.
        public void Throws()
        {
            throw new ArgumentException();
        }
    }

I use it from my client like so:

var baseAddress = new Uri("net.pipe://localhost/hello");

// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(TestService), baseAddress))
{
    var netBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
    host.AddServiceEndpoint(typeof(ITestService), netBinding, baseAddress);
    host.Open();

    Console.WriteLine("The service is ready at {0}", baseAddress);

    // Create client channel.
    var channel = ChannelFactory<ITestService>.CreateChannel(netBinding, new EndpointAddress(baseAddress));

    ((ICommunicationObject)channel).Open();

    try
    {
        foreach (var i in Enumerable.Range(0, 5000))
        {
            // channel dies after a few attempts.
            channel.Throws();
        }
    }

The method Throws is defined as IsOneWay = true, meaning it does not propogate any message back to the client (including errors).

When running in a loop, the communication object faults after some runs. I cannot figure out the cause of this.

The exception details:

System.ServiceModel.CommunicationException: There was an error writing to the pipe: The pipe is being closed. (232, 0xe8). ---> System.IO.PipeException: There was an error writing to the pipe: The pipe is being closed. (232, 0xe8). at System.ServiceModel.Channels.PipeConnection.StartSyncWrite(Byte[] buffer, Int32 offset, Int32 size, Object& holder) at System.ServiceModel.Channels.PipeConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout, BufferManager bufferManage r) --- End of inner exception stack trace ---

Note that if i change the body of Throws method to something else, like Console.WriteLine, everything is running fine.

EDIT: I have uploaded the sample project to my SkyDrive: http://sdrv.ms/NumUbR

In case someone wants to compile it locally and see if it behaves the same.

Answer

ErnieL picture ErnieL · Aug 13, 2012

You are simply exceeding the available bandwidth at some point. It’s likely the pipe, but it might also be in the WCF stack… processing exceptions is expensive and you are doing 5000 of them in as tight a loop as possible. Changing from an exception to a WriteLine() that returns nothing fixes the problem because it dramatically reduces the required bandwidth/processing. (I do see you mentioned OneWay, but I don't think it changes much. Even if the exception isn't returned, it still has to be processed).

Try changing InstanceContextMode to PerCall. That's the standard setting for “high volume” services. It will relieve some of the congestion.

Also to address the comments, hosting the service like this is fine. The ServiceHost will manage its own threads.