Diciamo solo che hai una semplice operazione che gira su un thread in background. Si desidera fornire un modo per annullare questa operazione in modo da creare un flag booleano impostato su true dal gestore di eventi click di un pulsante di annullamento.Devo bloccare o contrassegnare come volatile quando si accede a un semplice flag booleano in C#?
private bool _cancelled;
private void CancelButton_Click(Object sender ClickEventArgs e)
{
_cancelled = true;
}
Ora stai impostando il flag di annullamento dal thread della GUI, ma lo stai leggendo dal thread in background. Hai bisogno di bloccare prima di accedere al bool?
avresti bisogno per fare questo (e bloccare ovviamente nel gestore di eventi click tasto troppo):
while(operationNotComplete)
{
// Do complex operation
lock(_lockObject)
{
if(_cancelled)
{
break;
}
}
}
O è accettabile per fare questo (senza serratura):
while(!_cancelled & operationNotComplete)
{
// Do complex operation
}
O che dire della variabile _cancelled come volatile. È necessario?
[So che esiste la classe BackgroundWorker con il suo metodo CancelAsync() integrato, ma mi interessa la semantica e l'uso di accesso variabile e con accesso variabile ai thread qui, non l'implementazione specifica, il codice è solo un esempio. ]
Sembra esserci due teorie.
1) Perché è un semplice tipo integrato (e l'accesso ai tipi incorporati è atomico in .net) e poiché ci stiamo solo scrivendo in un posto e solo leggendo sul thread in background non è necessario bloccare o segna come volatile.
2) Dovresti contrassegnarlo come volatile perché se non lo fai il compilatore può ottimizzare la lettura del ciclo while perché non pensa nulla che sia in grado di modificare il valore.
Qual è la tecnica corretta? (E perché?)
[Modifica: Sembra che ci siano due scuole di pensiero chiaramente definite e opposte su questo. Sto cercando una risposta definitiva su questo quindi per favore se possibile postare le tue ragioni e citare le tue fonti insieme alla tua risposta.]
Sì, è * necessario * bisogno di 'volatile' o' lock' (per fungere da barriera di memoria): vedere http://stackoverflow.com/questions/458173/can-ac-thread-really-cache- valore-e-ignora-cambia-a-quel-valore-su-altro-th/458193 # 458193 –
Ciò significa che Simon sarà lasciato rosso di fronte al dibattito di massa che ha avuto con EFraim (http : //stackoverflow.com/questions/1221839/c-break-out-of-loop-on-button-press/1221854#1221854) – ThePower
@Marc: Bel esempio, grazie. @ThePower: Sono felice di alzare le mani quando non ne sono sicuro, quindi spero di evadere solo leggermente di rosa = :) –