NamedPipeServerStream.EndWaitForConnection () просто зависает при использовании - PullRequest
10 голосов
/ 05 февраля 2012

Я пытаюсь использовать именованные каналы впервые. В документации MS, найденной здесь , говорится, что:

EndWaitForConnection должен вызываться ровно один раз для каждого вызова BeginWaitForConnection.

Поэтому я стараюсь быть хорошим программистом и слежу за документацией, но EndWaitForConnection() просто зависает на неопределенное время, когда я его использую. * * 1010

Итак, я сократил свой код до минимума, чтобы посмотреть, смогу ли я выделить проблему, но без кубиков. Я вытащил следующий код из класса, который я написал. Я изменил его так, что он начинает ожидать подключения к каналу, а затем сразу же пытается остановить ожидание на этом подключении канала:

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) Почему висит на EndWaitForConnection()? Если я хочу закрыть свой сервер до получения соединения, как я могу по существу отменить этот BeginWaitForConnection() обратный вызов?

2) Давайте предположим, что у меня не было вышеупомянутой проблемы. Что произойдет, если 2 клиента попытаются подключиться к моему именованному каналу очень быстро?

Получу ли я обратный вызов для каждого из них, или мне нужно подождать, чтобы получить уведомление о первом подключении, затем быстро позвонить EndWaitForConnection(), а затем WaitForConnectionCallBack() снова, чтобы снова начать прослушивание следующего клиента?

Последнее кажется мне условием гонки, потому что я не могу настроить слушателя соединения достаточно быстро.

1 Ответ

9 голосов
/ 07 февраля 2012

Итак, основной каркас работающего для меня решения выглядит следующим образом:

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.
}
...