"Une référence à un domaine volatile ne sera pas considérée comme volatile" implications

le code suivant

using System.Threading;

class Test
{
    volatile int counter = 0;
    public void Increment()
    {
        Interlocked.Increment(ref counter);
    }
}

augmente l'avertissement de compilateur suivant:

"A reference to a volatile field will not be treated as volatile"

est-ce que je fais quelque chose de mal ici pour élever cet avertissement? Pourquoi le compilateur m'avertir à ce sujet?

39
demandé sur Jader Dias 2009-01-08 20:24:40

4 réponses

vous ne faites rien de mal. Selon la documentation :

un champ volatile ne devrait pas normalement être transmis en utilisant un ref ou un out paramètre, puisqu'il ne sera pas traités comme des volatiles dans le champ d'application de la fonction. Il y a des exceptions pour cela, comme lors de l'appel d'un interloqué de l'API.

40
répondu Darin Dimitrov 2009-01-08 17:29:20

fondamentalement, l'avertissement est que lorsque vous passez un champ volatile par référence, le code appelant ne sait pas le traiter d'une manière volatile. Pour Interloqué.Incrément qui n'a probablement pas d'importance, en raison de la nature de la méthode - mais alors vous n'avez pas besoin que la variable soit volatile de toute façon si vous utilisez Interlocked.

en général, je pense que j'éviterais de mélanger les deux - si vous utilisez entrelacés, le faire partout (en utilisant Interlocked.CompareExchange(ref counter, 0, 0) pour le lire). Je ne peux pas dire que j'utilise volatile très souvent, personnellement. Pour les compteurs simples I pourrait utiliser enclenché, mais je suis plus susceptible d'utiliser un verrou pour la plupart des tâches.

30
répondu Jon Skeet 2009-01-08 17:28:47

utilisez ceci:

        #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
26
répondu Robert Fraser 2015-06-16 03:24:28

vous obtenez l'erreur parce que vous passez le champ par référence. Je pense que cela signifie que la méthode cible n'a aucune idée que le champ est marqué volatile , et donc ne le traitera pas comme tel.

3
répondu Kent Boogaart 2011-09-28 00:53:43