2014-02-21 4 views
3

Я использую анонимные каналы для отправки команд между двумя процессами. Обычно все отлично работает, но время от времени команда, полученная потребителем, усекается, и только половина ее проходит.AnonymousPipes - не получать все данные

Это, как я посылать команды:

AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out,  HandleInheritability.Inheritable); 
StreamWriterpipeWriter = new StreamWriter(this.pipeServer) { AutoFlush = true }; 
pipeWriter.WriteLine(command); 

и это, как я прочитал их:

AnonymousPipeClientStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, pipeId); 
StreamReader pipeReader = new StreamReader(this.pipeClient); 
string command = pipeReader.ReadLine(); 

Команда на самом деле небольшой base64 преобразованный PDF-файл с некоторыми дополнительными данными. Команда, написанная в pipeWriter, имеет правильную форму (по крайней мере, журналы говорят нам об этом), а команда, полученная потребителем, обычно в порядке. Затем время от времени это не так и по какой-то причине потребитель получает только часть его.

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

Есть ли какая-либо известная причина возникновения этой ситуации? Мне что-то не хватает?

ответ

2

Это причуда в базовой реализации Windows для труб. Он не различает «я закрыл трубку, потому что что-то пошло не так» и «Я закрыл трубку, потому что я покончил с ней». Он реализует первое, выбрасывает данные в буфере и, следовательно, требует, чтобы писатель явно убедился, что данные, хранящиеся в буфере трубопровода, сделали его клиенту до его закрытия. Собственной функцией winapi является FlushFileBuffers().

Классы оболочки .NET могли бы сделать это немного понятнее, но они этого не сделали. Поэтому вы должны сделать это явным, и для вызова функции FlushFileBuffers() требуется вызвать WaitForPipeDrain(). Сделайте это непосредственно перед тем, как вы вызовете Close() или Dispose() на вашем анонимном сервере. И не делайте этого, когда вы закрываете трубу из-за исключения.

+0

Отличный ответ. Спасибо! – wade

3

На стороне писателя вам необходимо позвонить WaitForPipeDrain, прежде чем закрыть трубу.

+0

Почему? Я не хочу ждать до конца. – wade

+0

@wade: Вы хотите, чтобы труба переполнилась? Вы хотите иметь дело с этим беспорядком ?! :) –

+0

В нашем случае вероятность переполнения низкая, и на самом деле не требуется ждать ... но это будет иметь значение в случае нашей ошибки вообще? – wade

Смежные вопросы