2010-07-21 29 views
8

Estoy escribiendo una aplicación con una interfaz de comunicaciones en capas.
Esto se hizo para abstraer las comunicaciones de la parte de la interfaz de usuario de la aplicación y también para hacerla más escalable/mantenible.
Por ejemplo:Manejo de condiciones de carrera en C#

alt text

considerar cada cuadro en la figura anterior como una clase separada.
La interfaz de comunicación genérica completa las variables de cadena que describen los datos transaccionados y las comunicaciones "salud", que a su vez se copian a la aplicación a través de una serie de llamadas a funciones públicas. Por ejemplo, la aplicación podría hacer una llamada a la App-Sub-System:

class Application 
{ 
    private void SomeUpdateFunction() 
    { 
     this.textBox1.AppendText(this.AppSubSystem.GetText()); 
    } 
} 

class AppSubSystem 
{ 
    public string GetText() 
    { 
     return this.GenericCommsInterface.GetText(); 
    } 
} 

class GenericCommsInterface 
{ 
    public string GetText() 
    { 
     string sRetVal = this.sText; // sText is populated by other functions in the class. 
     this.sText = null; // Suspected race condition is here. 
     return sRetVal; 
    } 
} 

sText se rellena de forma asíncrona por otras funciones en la clase.
Creo que una condición de carrera está sucediendo entre string sRetVal = this.sText; y la siguiente línea this.sText = null;.
¿Alguien puede sugerir una forma de evitar o prevenir esta condición de carrera? ¿Ayudaría usar StringBuilder ayuda, o hay otra forma en que debería estar haciendo esto?

Respuesta

4

Probablemente esté adquiriendo un bloqueo cada vez que desee tocar this.sText - en las funciones que lo actualizan, así como en su función GetText. Esto aseguraría que solo un hilo a la vez esté jugando con él, ya que (suponiendo que el hilo tenga el bloqueo) otros hilos se asentarán y esperarán hasta que se complete el hilo actual.

Te recomiendo que utilices un StringBuilder, en parte para simplificar el bloqueo, ya que bloquear una cadena que se interceptó, o una cambiada en el medio de la operación bloqueada (y desbloqueada desde la perspectiva de un forastero) podría causa verdadero mal mojo. Algo como esto ayudaría:

lock (this.sbText) 
{ 
    sRetVal = this.sbText.ToString(); 
    this.sbText.Length = 0; 
} 

Como alternativa, puede bloquear el this, pero eso es feo - las cerraduras deben estar en el interior, lo más privada posible, con el fin de evitar los efectos secundarios extraños (como si algún otro objeto intentaba adquirir un bloqueo en este objeto; no podía hacerlo mientras se estaba alterando sbText).

+1

Muy malo para 'bloquear' en un objeto que no está garantizado para ser estable a través del acceso al hilo - los bloqueos son 'asesores' ya que todos deben usarlos/respetarlos. Esto es particularmente malo porque sigues cambiando el objeto de bloqueo (estableciendo la variable que lo contiene en nulo). –

+0

Buen punto.Otra razón para usar un StringBuilder. – cHao

+0

¡Gracias por los consejos! Reemplacé 'private string sText' con' private StringBuilder cText' e implementé los bloqueos. ¡Funciona genial! La condición de carrera ha desaparecido. ¡Prestigio! –

1
public string GetText() 
{ 
    lock(someObject) 
    { 
     string sRetVal = this.sText; // sText is populated by other functions in the class. 
     this.sText = null; // Suspected race condition is here. 
     return sRetVal; 
    } 
}  

en su conjunto

lock(someObject) 
{ 
    //... 
    this.sText = value; 
} 
+0

Esto * NO * lo hará - se podría escribir una nueva cadena después de la lectura pero antes del nulo. Toda la operación debe estar protegida, no solo las partes. –

+0

la internación te morderá en las regiones inferiores. El bloqueo de una cuerda es peor que no bloquearlo en absoluto. –

+0

No estoy en desacuerdo, pero no definí mi objeto de bloqueo en absoluto, y mucho menos lo definí como cadena. Estaba asumiendo que él podría tomar la esencia del asunto y completar los espacios en blanco. –

1

Este código lo más ciertamente no va a funcionar en un entorno de rosca, ya que no está protegiendo sText. Debes bloquear a todos los que accedan a él.

+1

Funcionará - * algunas veces *. Otras veces, los mensajes desaparecerán misteriosamente. – cHao

+1

El trabajo a veces no funciona. –

+3

Trabajo 8 (ish) horas al día. ¿Estoy desempleado? :) –

Cuestiones relacionadas