Estoy trabajando en una biblioteca de cliente/servidor para una implementación de RPC heredada y me encontré con problemas en los que el cliente a veces se bloquea al esperar recibir un mensaje de respuesta a un mensaje de solicitud de RPC. Resultó que el problema real estaba en mi código de encuadre de mensaje (no manejaba correctamente los límites de los mensajes al leer datos del subyacente NetworkStream
), pero también me hizo sospechar del código que estaba usando para enviar datos a través de la red, específicamente en el caso en que el servidor RPC envía una gran cantidad de datos a un cliente como resultado de una solicitud de RPC del cliente.¿Stream.Write es seguro para subprocesos?
Mi código de envío usa un BinaryWriter
para escribir un "mensaje" completo al NetworkStream
subyacente. El protocolo RPC también implementa un algoritmo de latido, donde el servidor RPC envía mensajes PING cada 15 segundos. Los pings se envían por un hilo separado, por lo que, al menos en teoría, se puede enviar un ping mientras el servidor está en medio de la transmisión de una gran respuesta a un cliente.
Supongamos que tengo un método Send
de la siguiente manera, donde stream
es una 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();
}
Así que la pregunta que tengo es, es el llamado a bw.Write
(y por ende la llamada a los subyacentes Stream
's Write
método) atómico? Es decir, si un largo Write
todavía está en progreso en el hilo de envío, y el hilo del latido interrumpe y envía un mensaje PING, ese hilo se bloqueará hasta que finalice la llamada original Write
, o debo agregar sincronización explícita al Send
método para evitar que las dos llamadas Send
golpeen la transmisión?
Lo vi también, pero como ese descargo de responsabilidad se aplica a casi todas las clases del BCL, me pregunté si podría haber una excepción para 'Stream' que podría haber pasado por alto en otra parte de la documentación. –
Lo siento, pero no que yo sepa. Asegúrate de tomarlo en tus propias manos para asegurarte de que esta sección de código sea segura para subprocesos. –
No hay necesidad de disculparse;). Estoy de acuerdo en que añadir sincronización explícita sería lo más seguro y lógico en cualquier caso. Solo tenía curiosidad si ya estaba "incorporado" a 'Stream', ya que la cláusula de exención de responsabilidad" thread-safe "no descarta la posibilidad. MSDN tiende a ser un poco vago a veces. –