Digamos que tiene una operación simple que se ejecuta en una cadena de fondo. Desea proporcionar una forma de cancelar esta operación para que cree un indicador booleano que establezca como verdadero desde el controlador de evento click de un botón cancelar.¿Debo bloquear o marcar como volátil cuando accedo a un indicador booleano simple en C#?
private bool _cancelled;
private void CancelButton_Click(Object sender ClickEventArgs e)
{
_cancelled = true;
}
Ahora está configurando el indicador de cancelación del hilo de la GUI, pero lo está leyendo desde el hilo de fondo. ¿Necesita bloquear antes de acceder al bool?
se necesita para hacer esto (y, obviamente, bloquear en el botón de controlador de eventos click también):
while(operationNotComplete)
{
// Do complex operation
lock(_lockObject)
{
if(_cancelled)
{
break;
}
}
}
O es aceptable para hacer esto (sin bloqueo):
while(!_cancelled & operationNotComplete)
{
// Do complex operation
}
O qué tal marcar la variable cancelada como volátil. ¿Es eso necesario?
[Sé que existe la clase BackgroundWorker con su método incorporado Incorporated CancelAsync(), pero me interesa la semántica y el uso de acceso variable con bloqueo y subprocesos aquí, no la implementación específica, el código es solo un ejemplo. ]
Parece que hay dos teorías.
1) Debido a que es un tipo simple incorporado (y el acceso a tipos incorporados es atómico en .net) y porque solo estamos escribiendo en un solo lugar y solo leyendo en el hilo de fondo no hay necesidad de bloquear o marca como volátil.
2) Debe marcarlo como volátil porque si no lo hace, el compilador puede optimizar la lectura en el ciclo while porque no cree que sea capaz de modificar el valor.
¿Cuál es la técnica correcta? (¿Y por qué?)
[Editar: Parece que hay dos escuelas de pensamiento claramente definidas y opuestas sobre esto. Estoy buscando una respuesta definitiva sobre esto así que, si es posible, publique sus razones y cite sus fuentes junto con su respuesta.]
Sí, usted * necesita * ya sea 'volátil' o' lock' (para actuar como una barrera de memoria): vea http://stackoverflow.com/questions/458173/can-ac-thread-really-cache- a-value-and-ignore-changes-to-that-value-on-other-th/458193 # 458193 –
Esto significa que Simon se va a quedar con la cara roja en el debate masivo que ha tenido con EFraim (http : //stackoverflow.com/questions/1221839/c-break-out-of-loop-on-button-press/1221854#1221854) – ThePower
@Marc: Buen ejemplo, gracias. @ThePower: estoy contento de levantar las manos cuando no estoy seguro, así que espero escapar solo ligeramente rosada = :) –