"Un riferimento a un campo volatile non sarà trattato come volatile" implicazioni
-
06-07-2019 - |
Domanda
Il seguente codice
using System.Threading;
class Test
{
volatile int counter = 0;
public void Increment()
{
Interlocked.Increment(ref counter);
}
}
Genera il seguente avviso del compilatore:
"A reference to a volatile field will not be treated as volatile"
Sto facendo qualcosa di sbagliato qui per sollevare questo avviso? Perché il compilatore mi avvisa di questo?
Soluzione
Non stai facendo nulla di male. Secondo la documentazione :
Un campo volatile non dovrebbe normalmente essere passato usando un ref o out parametro, poiché non lo sarà trattato come volatile nell'ambito della funzione. Ci sono eccezioni a questo, come quando si chiama un API interbloccata.
Altri suggerimenti
Fondamentalmente l'avvertimento è che quando si passa un campo volatile per riferimento, il codice chiamante non sa come trattarlo in modo volatile. Per Interlocked.Increment che probabilmente non ha importanza, a causa della natura del metodo, ma non è necessario che la variabile sia volatile comunque se si utilizza Interlocked.
In generale, penso che eviterei di mescolare i due: se stai usando Interlocked, fallo ovunque (usando Interlocked.CompareExchange (ref counter, 0, 0)
per leggerlo). Non posso dire di usare volatile molto spesso, personalmente. Per i contatori semplici, potrei utilizzare Interbloccato, ma ho maggiori probabilità di utilizzare un blocco per la maggior parte delle attività.
Usa questo:
#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
Stai ricevendo l'errore perché stai passando il campo per riferimento. Penso che ciò significhi che il metodo target non ha idea che il campo sia contrassegnato come volatile
, e quindi non lo tratterà come tale.