NamedPipeServerStream.EndWaitForConnection()在使用时会挂起

Ult*_*nks 10 c# asynchronous named-pipes interprocess

我第一次尝试使用命名管道.在此处找到的MS文档中,它指出:

对于每次调用BeginWaitForConnection,必须只调用一次EndWaitForConnection.

所以我想成为一个优秀的小程序员并遵循文档,但是EndWaitForConnection()当我使用它时,它会无限期地挂起.

所以我把我的代码剥离到最低限度,所以看看我是否可以隔离问题而不是骰子.我已经从我写过的课程中提取了以下代码.我已修改它,以便它开始在管道连接上等待,然后立即尝试停止等待该管道连接:

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
}
Run Code Online (Sandbox Code Playgroud)

1)为什么要坚持下去EndWaitForConnection()?如果我想在收到连接之前关闭我的服务器,我怎么能基本上取消这个BeginWaitForConnection()回调?

2)我们假设我没有上述问题.如果2个客户端尝试很快连接到我的命名管道会发生什么?

我是否为每个人获得了回调调用,或者我是否必须等待接收第一个连接通知EndWaitForConnection()然后 WaitForConnectionCallBack()再次快速呼叫再次开始侦听下一个客户端?

后者对我来说似乎是一种竞争条件,因为我可能不会足够快地设置连接侦听器.

Ult*_*nks 9

因此,对我有用的解决方案的基本框架如下:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是服务器代码.

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.
}
Run Code Online (Sandbox Code Playgroud)