5

私は単純な非同期 NamedPipeStreamServer プロセスを C# で作成しました。その核心は次のとおりです。

public void Listen()
{
    bool shuttingDown = false;
    while (!shuttingDown)
    {
        NamedPipeServerStream serverStream =
            new NamedPipeServerStream(
                "bobasdfpipe",
                PipeDirection.InOut,
                254,
                PipeTransmissionMode.Message,
                PipeOptions.Asynchronous);

        IAsyncResult connectionResult = 
                serverStream.BeginWaitForConnection(
                    this.HandleConnection,
                    serverStream);

        int waitResult =
            WaitHandle.WaitAny(
                new[]
                    {
                        this.ShutdownEvent,
                        connectionResult.AsyncWaitHandle
                    });
        switch (waitResult)
        {
            case 0:
                // this.ShutdownEvent
                shuttingDown = true;
                break;

            case 1:
                // connectionResult.AsyncWaitHandle
                serverStream.EndWaitForConnection(connectionResult);
                break;
        }
    }
}

そのための簡単なクライアントも作成しました。クライアント (非同期ではない) は、パイプを開いて終了するだけです。

static void Main(string[] args)
{
    using (
        NamedPipeClientStream clientStream =
            new NamedPipeClientStream(
                ".",
                "bobasdfpipe",
                PipeDirection.InOut))
    {
        clientStream.Connect();
    }
}

サーバーを起動してから、1 つまたは複数のクライアントを起動すると、すべて正常に動作しているように見えます。

サーバーを起動せずにクライアントを起動すると、クライアントはサーバーを起動するまで Connect() 呼び出しでハングしますが、その後サーバーを起動すると、BeginWaitForConnection( の System.IO.Exception でサーバーがクラッシュします。 )「パイプが閉じられています」と言って呼び出します。

BeginWaitForConnection() で「パイプが閉じられています」というエラーが発生している他の人を見つけましたが、それらはすべて、同じ NamedPipeServerStream インスタンスで 2 回目の BeginWaitForConnection() 呼び出しを試行したことが原因です。それはここで起こっていることではありません - 私は BeginWaitForConnection() 呼び出しごとに異なる NamedPipeServerStream インスタンスを作成します。

私は何か間違ったことをしていますか?それとも、これは正常なことですか? サーバーの起動を待機している名前付きパイプ クライアントは、サーバーの最初の BeginWaitForConnection() 呼び出しで「パイプが閉じられています」というメッセージを表示しますか?

再試行すると、つまり、例外を吸収して別の BeginWaitForConnection() を実行すると、サーバーが起動するのを待っていたすべてのクライアントに対して 1 つの例外が発生することに気付きましたが、それらすべてを処理した後、その後、サーバーは正常に動作しているようです。

編集:これがHandleConnectionメソッドですが、このコードにさえ当たらないと思います:

private void HandleConnection(IAsyncResult iar)
{
    NamedPipeServerStream serverStream =
        (NamedPipeServerStream)iar.AsyncState;

    Log.Info("So, that happened.");
    Thread.Sleep(1000);
    Log.Info("Giving up.");
}
4

1 に答える 1

3

サーバーによって完全に処理される前に、クライアントが接続を閉じているようです。clientStream.Dispose()直後に が呼び出され 、確立しようとしていた接続が切断されるために発生clientStream.Connect()します。 ヒント:Thread.Sleep(100)の直後clientStream.Connect()に追加してみてください。

私は何か間違ったことをしていますか?それとも、これは正常なことですか? サーバーの起動を待機している名前付きパイプ クライアントは、サーバーの最初の BeginWaitForConnection() 呼び出しで「パイプが閉じられています」というメッセージを表示しますか?

クライアントが何を行うかに関係なく、サーバー コードは、IOExceptionをキャッチしてサーバーのパイプ ハンドルを破棄することにより、この一連のイベントを適切に処理できる必要があります。

   NamedPipeServerStream serverStream =
        new NamedPipeServerStream(
            "bobasdfpipe",
            PipeDirection.InOut,
            254,
            PipeTransmissionMode.Message,
            PipeOptions.Asynchronous);

    try 
    {  
        IAsyncResult connectionResult = serverStream.BeginWaitForConnection(
                this.HandleConnection,
                serverStream);


       int waitResult =
           WaitHandle.WaitAny(
               new[]
                {
                    this.ShutdownEvent,
                    connectionResult.AsyncWaitHandle
                });
        switch (waitResult)
        {
          case 0:
            // this.ShutdownEvent
            shuttingDown = true;
            break;

          case 1:
            // connectionResult.AsyncWaitHandle
               serverStream.EndWaitForConnection(connectionResult);
               break;
         }    

    }
    catch(IOException)
    {
        // Connection terminated by client, close server pipe's handle
        serverStream.Close();
        continue;
    }
于 2016-03-30T18:55:55.997 に答える