6

非同期で実行される再利用可能な名前付きパイプリスナーを作成する方法の良い例を見つけることができません。再利用可能なリスナーを作成できます。

NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut);

    while (true)
    {
            pipeServer.WaitForConnection();

            StreamReader reader = new StreamReader(pipeServer);

            MessageBox.Show(reader.ReadLine());

            pipeServer.Disconnect();
    }

非同期リスナーを作成できます。

NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);

    pipeServer.BeginWaitForConnection((a) =>
    {
        pipeServer.EndWaitForConnection(a);

        StreamReader reader = new StreamReader(pipeServer);
        MessageBox.Show(reader.ReadLine());

    }, null);

しかし、私は両方をうまくやることができないようです。これの良い例はありますか?このような非同期通信の問題だと思うので、部分的に送信されたメッセージについても心配しています。

更新:私は少し近づいています。

pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);

pipeServer.BeginWaitForConnection((a) =>
{
    pipeServer.EndWaitForConnection(a);

    StreamReader reader = new StreamReader(pipeServer);

    while (running)
    {
        String text = reader.ReadLine();

        if (String.IsNullOrEmpty(text) == false)
        {
            MessageBox.Show(text);
        }
    }

    MessageBox.Show("Done!");

}, null);

これは1回正常に読み取られ、ループを継続します。ReadLineは、最初の正常な読み取りの後に空の空の文字列を返します。したがって、明らかにブロックされておらず、再度読み取ろうとしています。問題は、同じメッセージを2回送信しても受信されず、パイプライターがエラー2316を受信して​​いると言っていることです(それが何を意味するのかはわかりませんが)。最初にリストしたコードサンプルのように、パイプが毎回クリーンアップされるのと同じようなことをする必要があると思いますが、まだそれが機能するようにはなりません。

4

2 に答える 2

7

私はそれを持っていると思います:

pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);

Boolean connectedOrWaiting = false;

Byte[] buffer = new Byte[65535];

while (running)
{
    if (!connectedOrWaiting)
    {                   
        pipeServer.BeginWaitForConnection((a) => { pipeServer.EndWaitForConnection(a); }, null);

        connectedOrWaiting = true;
    }

    if (pipeServer.IsConnected)
    {
        Int32 count = pipeServer.Read(buffer, 0, 65535);

        if (count > 0)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String message = encoding.GetString(buffer, 0, count);

            MessageBox.Show(message);
        }

        pipeServer.Disconnect();

        connectedOrWaiting = false;
    }
}

これは複数のメッセージが来ると受け入れ、running が false に設定されるとすぐにシャットダウンします (明らかに別のスレッドで)。それは私が必要としているもののようです。私がばかげたことをしていないことを誰かが確認できますか?

于 2010-09-28T20:17:59.107 に答える
2

部分的に送信されたメッセージも気になる

これらは、ネイティブ (Win32) API を使用する NamedPipes の問題ではないため、.NET を使用する場合の問題であるとは思えません。ただし、ネイティブのドキュメントでは次のように述べています。

データは、メッセージのストリームとしてパイプに書き込まれます。パイプは、各書き込み操作中に書き込まれたバイトをメッセージ ユニットとして扱います。メッセージが完全に読み取られていない場合、GetLastError 関数は ERROR_MORE_DATA を返します。このモードは、PIPE_READMODE_MESSAGE または PIPE_READMODE_BYTE のいずれかで使用できます。

(注ERROR_MORE_DATAは 234 です。)

ドキュメントには、フラグFILE_FLAG_OVERLAPPED(ネイティブに相当するものPipeOptions.Asynchronous)についても記載されています。

オーバーラップ モードが有効です。このモードが有効になっている場合、完了するまでにかなりの時間がかかる可能性のある読み取り、書き込み、および接続操作を実行する関数は、すぐに戻ることができます。

私は常に非同期の名前付きパイプ (つまりStream.BeginRead) で非同期 IO 操作を使用してきましたが、これは の機能を失うことを意味しますが、TextReaderとにかくPipeTransmissionMode.Messageバイトのグループを送信するという観点から定義されています。

于 2010-09-28T16:05:43.817 に答える