2012-02-04 27 views
8

Próbuję użyć nazwanych potoków po raz pierwszy. W dokumentacji MS stwierdzono here, stwierdza, że:NamedPipeServerStream.EndWaitForConnection() po prostu zawiesza się po użyciu

EndWaitForConnection musi być wywołana dokładnie jeden raz na każde wezwanie do BeginWaitForConnection.

Więc staram się być dobrą trochę programista i postępuj zgodnie z dokumentacją, ale EndWaitForConnection() prostu wisi w nieskończoność, kiedy go używać.

Więc rozebrałem mój kod do absolutnego minimum, więc zobacz, czy mógłbym wyizolować problem, ale nie ma kości. Wyciągnąłem poniższy kod z klasy, którą napisałem. I zostały zmodyfikowane tak, że zaczyna oczekiwanie na połączenie rury natychmiast próbuje przestać czekać na tego połączenia rur:

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) Dlaczego to powiesić na EndWaitForConnection()? Jeśli chcę wyłączyć serwer, zanim otrzymam połączenie, jak zasadniczo anulować to wywołanie zwrotne od BeginWaitForConnection()?

2) Załóżmy, że nie miałem wyżej wymienionego problemu. Co się stanie, jeśli 2 klienci bardzo szybko spróbują połączyć się z moją nazwaną siecią?

Czy otrzymuję wywołanie zwrotne dla każdego z nich, czy muszę czekać na otrzymanie pierwszego powiadomienia o połączeniu, a następnie szybko ponownie zadzwonić pod numer EndWaitForConnection(), a następnie WaitForConnectionCallBack(), aby ponownie zacząć słuchać następnego klienta?

Ten ostatni wydaje się być dla mnie warunkiem wyścigowym, ponieważ może nie ustawić wystarczająco szybko odbiornika połączenia.

+0

Zgodnie z projektem, to wywołanie powinno być używane tylko w metodzie wywołania zwrotnego (WaitForConnectionCallBack). Anulujesz to, wywołując funkcję tempPipe.Close(). –

+0

Tak, ja sam doszedłem do tego wniosku. Zasadniczo odkryłem, że wywołanie funkcji tempPipe.Close() powoduje natychmiastowe wywołanie procedury wywołania zwrotnego, problem polega na tym, że ustawiłem go tak, aby natychmiast wywoływał EndWaitForConnection, ale ponieważ rura jest wtedy zamknięta, zgłasza wyjątek. Musiałem więc owinąć instrukcję try i nic nie robić w instrukcji catch. Czy to jest poprawne rozwiązanie? Wydaje mi się, że jest mi trochę niedbale, gdybym zamknął rurkę, wiedząc, że wymusi wyjątek w twoim wywołaniu zwrotnym, który będziesz musiał złapać. – Ultratrunks

+0

To zupełnie normalne. –

Odpowiedz

8

Więc podstawowy szkielet rozwiązania, które pracuje dla mnie jest następująca:

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

Oto kod serwera.

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

FYI Zobacz [C# UnauthorizedAccessException podczas włączania MessageMode dla potoku o nazwie tylko do odczytu (NamedPipeClientStream class)] (http://stackoverflow.com/questions/32739224/c-sharp-unauthorizedaccessexception-when-enabling-messagemode-for-read-only -name) dla innych informacji o korzystaniu z trybu "Message". – OmegaMan

Powiązane problemy