"Una referencia a un campo volátil no se tratará como volátil" implicaciones
-
06-07-2019 - |
Pregunta
El siguiente código
using System.Threading;
class Test
{
volatile int counter = 0;
public void Increment()
{
Interlocked.Increment(ref counter);
}
}
Genera la siguiente advertencia del compilador:
"A reference to a volatile field will not be treated as volatile"
¿Estoy haciendo algo mal aquí para generar esta advertencia? ¿Por qué el compilador me advierte sobre esto?
Solución
No estás haciendo nada malo. De acuerdo con la documentación :
Un campo volátil no debería normalmente ser aprobado usando una referencia o fuera parámetro, ya que no será tratado como volátil dentro del alcance de la función. Hay excepciones a esto, como cuando se llama a un API entrelazada.
Otros consejos
Básicamente, la advertencia es que cuando pasa un campo volátil por referencia, el código de llamada no sabe tratarlo de manera volátil. Para Interlocked. Incremento que probablemente no importa, debido a la naturaleza del método, pero entonces no necesita que la variable sea volátil de todos modos si usa Interlocked.
En general, creo que evitaría mezclar los dos: si usa Interlocked, hágalo everywhere (utilizando Interlocked.CompareExchange (ref counter, 0, 0) para leerlo). No puedo decir que uso volatile muy a menudo, personalmente. Para contadores simples, podría usar Interbloqueado, pero es más probable que use un bloqueo para la mayoría de las tareas.
Use esto:
#pragma warning disable 420
// M
// dM
// MMr
// 4MMML .
// MMMMM. xf
// . "MMMMM .MM-
// Mh.. +MMMMMM .MMMM
// .MMM. .MMMMML. MMMMMh
// )MMMh. MMMMMM MMMMMMM
// 3MMMMx. 'MMMMMMf xnMMMMMM"
// '*MMMMM MMMMMM. nMMMMMMP"
// *MMMMMx "MMMMM\ .MMMMMMM=
// *MMMMMh "MMMMM" JMMMMMMP
// MMMMMM 3MMMM. dMMMMMM .
// MMMMMM "MMMM .MMMMM( .nnMP"
// =.. *MMMMx MMM" dMMMM" .nnMMMMM*
// "MMn... 'MMMMr 'MM MMM" .nMMMMMMM*"
// "4MMMMnn.. *MMM MM MMP" .dMMMMMMM""
// ^MMMMMMMMx. *ML "M .M* .MMMMMM**"
// *PMMMMMMhn. *x > M .MMMM**""
// ""**MMMMhx/.h/ .=*"
// .3P"%....
// nP" "*MMnx
if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
return;
#pragma warning restore 420
Obtiene el error porque pasa el campo por referencia. Creo que lo que esto significa es que el método de destino no tiene idea de que el campo esté marcado como volatile
y, por lo tanto, no lo tratará como tal.