Как реализовать многоразовый прослушиватель именованных каналов, который работает асинхронно? - PullRequest
6 голосов
/ 27 сентября 2010

Я не могу найти хороший пример того, как создать многоразовый прослушиватель именованных каналов, который работает асинхронно.Я могу сделать слушателя многократного использования:

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

Он будет успешно прочитан один раз и продолжит цикл, а ReadLine вернет пустую пустую строку после первоначального успешного чтения.Так что он явно не блокирует и пытается прочитать снова.Проблема в том, что если я отправляю одно и то же сообщение во второй раз, оно не принимается, и мой писатель сообщает, что получает ошибку 2316 (хотя я не могу понять, что это значит).Я думаю, что мне просто нужно сделать что-то похожее на это, когда канал очищается каждый раз, как в первом примере кода, который я перечислил, но я пока не заставил это работать.

Ответы [ 2 ]

7 голосов
/ 29 сентября 2010

Я думаю, что у меня это есть:

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

Это примет несколько сообщений по мере их поступления и отключится, как только будет запущено значение false (очевидно, в другом потоке).Похоже, это то, что мне нужно.Может кто-нибудь проверить, что я не делаю глупостей?

2 голосов
/ 28 сентября 2010

Меня также беспокоят частично отправленные сообщения

Они не являются проблемой для NamedPipes, использующей нативные (Win32) API, поэтому я очень сомневаюсь, что они являются проблемой при использовании .NET. Однако в нативной документации говорится:

Данные записываются в канал как поток сообщений. Канал обрабатывает байты, записанные во время каждой операции записи, как единицу сообщения. Функция GetLastError возвращает ERROR_MORE_DATA, когда сообщение прочитано не полностью. Этот режим можно использовать с PIPE_READMODE_MESSAGE или PIPE_READMODE_BYTE.

(Примечание ERROR_MORE_DATA - 234.)

В документации также сказано, для флага FILE_FLAG_OVERLAPPED (собственный эквивалент PipeOptions.Asynchronous):

Режим перекрытия включен. Если этот режим включен, функции, выполняющие операции чтения, записи и подключения, выполнение которых может занять значительное время, могут немедленно вернуться.

Я всегда использовал асинхронные операции ввода-вывода с асинхронными именованными каналами (то есть Stream.BeginRead), но это означает потерю функциональности TextReader, но затем В любом случае 1030 * определяется в терминах передающих групп байтов.

...