C# NamedPipeServerStream.EndWaitForConnection()在使用时仅挂起

C# NamedPipeServerStream.EndWaitForConnection()在使用时仅挂起,c#,asynchronous,named-pipes,interprocess,C#,Asynchronous,Named Pipes,Interprocess,我第一次尝试使用命名管道。在找到的MS文档中,它指出: EndWaitForConnection必须为对的每次调用准确调用一次 开始等待连接 因此,我试图成为一名优秀的小程序员并遵循文档,但是EndWaitForConnection()在我使用它时会无限期地挂起 因此,我将代码精简到最低限度,看看是否可以隔离问题,但不要冒险。我从我编写的类中提取了以下代码。我对其进行了修改,使其开始等待管道连接,然后立即尝试停止等待该管道连接: private void WaitForConnectionCal

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

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
}
private void WaitForConnectionCallBack(IAsyncResult结果)
{
}
公开作废开始()
{
var tempPipe=新名称pipeserverstream(“tempPipe”,
在,,
254, 
PipeTransmissionMode.Message,
管道选项(异步);
IAsyncResult结果=tempPipe.BeginWaitForConnection(
新的AsyncCallback(WaitForConnectionCallBack),这个;

tempPipe.EndWaitForConnection(result);//因此,对我有效的解决方案的基本框架如下:

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;
    }
}
这是服务器代码

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.
}
public void Start()
{
var server=new NamedPipeServerStream(“TempPipe”,
在,,
254, 
PipeTransmissionMode.Message,
管道选项(异步);
//如果没有任何连接,则永远不会调用回调。
BeginWaitForConnection(新的AsyncCallback(WaitForConnectionCallBack),this);
//…任意代码
//EndWaitForConnection()不是这里的正确答案,它将无限期地等待
//如果你叫它,就像汉斯·帕桑提到的,它是用来回调的。
//现在是这样。相反,我们将关闭管道。这将触发
//要调用的回调。
//但是,在回调中异常的EndWaitForConnection()将失败
//除了一个例外,因为管道在被调用时已关闭,
//因此,您必须用try/catch捕捉它

server.Close();//根据设计,该调用应该只在回调方法(WaitForConnectionCallBack)中使用。您可以通过调用tempPipe.Close()来取消它。是的,我自己也有过类似的结论。我基本上发现调用tempPipe.Close()获取立即移动的回调例程,问题是,我已将其设置为立即调用EndWaitForConnection,但由于管道在此之前已关闭,因此它会引发异常。因此,我必须围绕它包装一个try语句,并且在catch语句中不执行任何操作。这是正确的解决方案吗?关闭管道似乎有点草率,知道它会在回调中强制执行一个你必须捕获的异常。@HansPassant我刚刚编写了基本上相同的东西,我也对回调中的
ObjectDisposedException
感到惊讶。因为什么时候处理异常才是“预期的”处理方法?我不是说你错了,但这有意义吗?这是它应该工作的方式吗?是的,这是完全正常的。异步调用异常完成,异常说明了原因。不要像答案那样捕获它们,只捕获ODE。有关使用
Message
模式的其他信息,请参阅。