I'm trying to use named pipes for the first time. In the MS documentation found here, it states that:
EndWaitForConnection must be called exactly once for every call to BeginWaitForConnection.
So I'm trying to be a good little programmer and follow documentation, but the EndWaitForConnection()
just hangs indefinitely when I use it.
So I stripped down my code to a bare minimum so see if I could isolate the problem but no dice. I've pulled the following code out of a class I've written. I've modified it so that it begins waiting on a pipe connection then immediately tries to stop waiting on that pipe connection:
private void WaitForConnectionCallBack(IAsyncResult result)
{
}
public void Start()
{
var tempPipe = new NamedPipeServerStream("TempPipe",
PipeDirection.In,
254,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
IAsyncResult result = tempPipe.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), this);
tempPipe.EndWaitForConnection(result); // <----- Hangs on this line right here
}
1) Why does it hang on EndWaitForConnection()
? If I want to shut down my server before I've received a connection, how can I essentially cancel this BeginWaitForConnection()
callback?
2) Let's suppose that I did not have the above mentioned problem. What happens if 2 clients try to connect to my named pipe very quickly?
Do I get a callback invocation for each of them, or do I have to wait to receive the first connection notification then quickly call EndWaitForConnection()
then WaitForConnectionCallBack()
again to start listening for the next client again?
The latter seems like a race condition to me, because I may not set up the connection listener fast enough.
So, a basic skeleton of the solution that is working for me is as follows:
private void WaitForConnectionCallBack(IAsyncResult result)
{
try
{
PipeServer.EndWaitForConnection(result);
/// ...
/// Some arbitrary code
/// ...
}
catch
{
// If the pipe is closed before a client ever connects,
// EndWaitForConnection() will throw an exception.
// If we are in here that is probably the case so just return.
return;
}
}
Here is the Server code.
public void Start()
{
var server= new NamedPipeServerStream("TempPipe",
PipeDirection.In,
254,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
// If nothing ever connects, the callback will never be called.
server.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), this);
// ... arbitrary code
// EndWaitForConnection() was not the right answer here, it would just wait indefinitely
// if you called it. As Hans Passant mention, its meant to be used in the callback.
// Which it now is. Instead, we are going to close the pipe. This will trigger
// the callback to get called.
// However, the EndWaitForConnection() that will excecute in the callback will fail
// with an exception since the pipe is closed by time it gets invoked,
// thus you must capture it with a try/catch
server.Close(); // <--- effectively closes our pipe and gets our
// BeginWaitForConnection() moving, even though any future
// operations on the pipe will fail.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With