2010-03-09 11 views
6

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?

Respuesta

8

estáticos públicos (Shared en Visual Basic) de este tipo son el hilo seguro. Los miembros de instancia no son garantizados para ser seguros para subprocesos.

De Stream Class, por lo sin no se garantiza.

+1

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. –

+1

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. –

+1

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. –

2

No está documentado como atómico. Yo no asumiría que es así y definitivamente envolvería esas cosas en un mecanismo de bloqueo personalizado. Básicamente, todo el método de envío prácticamente pide un bloqueo.

0

Debe bloquear el escritor en ambos hilos para estar seguro. Afair the writer no es seguro para subprocesos.

Compruebe MSDN para "Monitor" y "Mutex".

Cuestiones relacionadas