Я работаю над клиент-серверной библиотекой для реализации RPC прежней версии и сталкивался с проблемами, где клиент будет иногда зависать при ожидании к получению ответного сообщения к сообщению запроса RPC. Оказывается, что настоящая проблема была в моем сообщении, структурирующем код (я не обрабатывал границы сообщения правильно при чтении данных от базового NetworkStream
), но это также сделало меня подозрительным к коду, который я использовал для отправки данных по сети, конкретно в случае, куда сервер RPC отправляет большой объем данных клиенту как результат клиента запрос RPC.
Мой отправлять использование кода a BinaryWriter
записать полное "сообщение" в базовое NetworkStream
. Протокол RPC также реализует алгоритм heartbeat, где сервер RPC отсылает сообщения PING каждые 15 секунд. Ping отосланы отдельным потоком, таким образом, по крайней мере, в теории, ping может быть отправлен, в то время как сервер посреди потоковой передачи большого ответа назад клиенту.
Предположим, что у меня есть a Send
метод следующим образом, где stream
a 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
все еще происходит на передающем потоке, и поток heartbeat вталкивает и отправляет сообщение PING, будет тот блок потока до оригинала Write
назовите концы или сделайте я должен добавить явную синхронизацию к Send
метод для предотвращения двух Send
вызовы от избиения потока?
Любые общедоступные статические (общие в Visual Basic) члены этого типа являются потокобезопасными . Нет гарантии, что любые члены экземпляра будут потокобезопасными.
Из Класс потока , поэтому нет это не гарантируется.
Вы должны заблокировать писатель в обоих потоках, чтобы быть уверенным. Если писатель не является потокобезопасным.
Найдите в MSDN «Монитор» и «Мьютекс».
Он не задокументирован как атомарный. Я бы не предполагал, что это так, и определенно обернул бы все это вокруг настраиваемого механизма блокировки. По сути, весь метод Send требует блокировки.