8

The following code creates a new thread acting first as a named pipe client for sending parameters and then as a server for retrieving results. After that it executes a function in another AppDomain acting as a named pipe server and after that as a client to send the results back.

public OrderPrice DoAction()
{
  Task<OrderPrice> t = Task<OrderPrice>.Factory.StartNew(NamedPipeClient, parameters);

  if (domain == null)
  {
    domain = AppDomain.CreateDomain(DOMAINNAME);
  }
  domain.DoCallBack(AppDomainCallback);

  return t.Result;
}

static OrderPrice NamedPipeClient(object parameters) {
  OrderPrice price = null;

  using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_TO)) {
    stream.Connect();
    SerializeToStream(stream, parameters);
  }

  using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_BACK)) {
    stream.WaitForConnection();

    price = (OrderPrice)DeserializeFromStream(stream);
  }

  return price;
}

void AppDomainCallback() {
  OrderPrice price = null;

  using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_TO)) {
    stream.WaitForConnection();

    List<object> parameters = (List<object>)DeserializeFromStream(stream);

    if (mi != null)
      price = (OrderPrice)mi.Invoke(action, parameters.ToArray());
}

  using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_BACK)) {
    stream.Connect();
    SerializeToStream(stream, price);
  }
}

The code is called once per second on average and it worked fine for 7+ hours. But at some point "system.io.ioexception all pipe instances are busy" is thrown and they wont reconnect anymore after that. Browsing here it seems like it could be because of not properly disposing the pipe objects, but I guess thats all good since they are inside using statements. Does anyone have any clue what could be wrong here? The code is in .NET 4.0 running on windows server 2008.

4
  • 4
    The exception is thrown when you try to access a pipe from multiple threads at once. Pipes are not thread-safe, are you sure you don't access them simultaneously with the two threads?
    – hcb
    Commented Aug 26, 2013 at 6:52
  • when creating multiple threads that call DoAction the code crashes on the first call because a second NamedPipeServerStream(PIPE_TO) instance is made. I tried adding lock(SyncToObject) but the code is entered twice still. I think because it runs in a separate AppDomain but Im not sure how to use objects in separate Appdomains Commented Aug 26, 2013 at 7:40
  • Can you move the call to AppDomainCallback() in to the task? Or is that method automatically called on another thread because it's in another domain?
    – hcb
    Commented Aug 26, 2013 at 8:16
  • 1
    it was indeed a Thread issue, thanks. Fixed it by adding lock(sync) at the highest level, in DoAction. Using four sync objects for the four pipe objects worked too but it makes the code halt every once in a while Commented Aug 26, 2013 at 8:50

2 Answers 2

2

Sounds like it should be a mutex instead of a simple lock

Lock, mutex, semaphore... what's the difference?

as far as the occasional halting, it could be starvation or a deadlock.

This is good reading material for abstracts on what may be happening

http://en.wikipedia.org/wiki/Dining_philosophers_problem

1

Another situation where you might get the error message: "System.IO.IOException: All pipe instances are busy" is:

When starting a NamedPipeServerStream, if the Pipe Name is already being used by another Server, it will throw this error. I'm not 100% sure if it only throws when the Max Instances are reached, but that may be the case.

Not the answer you're looking for? Browse other questions tagged or ask your own question.