Является ли Stream.Write поточно-ориентированным? - PullRequest
6 голосов
/ 09 марта 2010

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

Мой код отправки использует BinaryWriter для записи полного «сообщения» в базовый NetworkStream. Протокол RPC также реализует алгоритм пульса, при котором сервер RPC отправляет сообщения PING каждые 15 секунд. Пинги отправляются отдельным потоком, поэтому, по крайней мере, теоретически, пинг может быть отправлен, пока сервер находится в процессе потоковой передачи большого ответа клиенту.

Предположим, у меня есть метод Send следующим образом, где stream - это NetworkStream:

public void Send(Message message)
{
   //Write the message to a temporary stream so we can send it all-at-once
   MemoryStream tempStream = new MemoryStream();
   message.WriteToStream(tempStream);

   //Write the serialized message to the stream.
   //The BinaryWriter is a little redundant in this 
   //simplified example, but here because
   //the production code uses it.
   byte[] data = tempStream.ToArray();
   BinaryWriter bw = new BinaryWriter(stream);
   bw.Write(data, 0, data.Length);
   bw.Flush();
}

Таким образом, у меня есть вопрос: является ли вызов bw.Write (и, как следствие, вызов базового метода Stream Write) атомарным? То есть, если в потоке-отправителе все еще выполняется длительный Write, и поток сердцебиения запускает и отправляет сообщение PING, будет ли этот поток блокироваться до завершения исходного вызова Write или мне нужно добавить явное синхронизация с методом Send, чтобы два Send вызова не могли заглушить поток?

Ответы [ 3 ]

9 голосов
/ 09 марта 2010

Любые открытые статические (Shared в Visual Basic) члены этого типа являются потокобезопасными.Любые члены экземпляра не гарантированно являются потокобезопасными.

С Класс потока , поэтому нет это не гарантируется.

2 голосов
/ 09 марта 2010

Это не зарегистрировано как атомное. Я не предполагал бы, что это так, и определенно обернул бы это вокруг пользовательского механизма блокировки. В целом весь метод Send в значительной степени требует блокировки.

0 голосов
/ 09 марта 2010

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

Проверьте MSDN для «Монитор» и «Mutex».

...