Question

Dans mon application, j'ai un formulaire qui démarre le processus de synchronisation et, pour un certain nombre de raisons, je souhaite autoriser l'exécution d'une seule synchronisation à la fois. J'ai donc ajouté un champ statique bool à mon formulaire indiquant si la synchronisation est en cours et ajouté un verrou pour définir ce champ sur true s'il n'était pas déjà défini de sorte que le premier thread puisse démarrer la synchronisation, mais lorsqu'il exécute tous les autres threads. va essayer de commencer il va se terminer.

Mon code ressemble à quelque chose comme ceci:

internal partial class SynchronizationForm : Form
{
    private static volatile bool workInProgress;

    private void SynchronizationForm_Shown(object sender, EventArgs e)
    {
        lock (typeof(SynchronizationForm))
        {
            if (!workInProgress)
            {
                workInProgress = true;
            }
            else
            {
                this.Close();
            }
        }
    }
}

Cela fonctionne bien, mais lorsque je lance l'analyse de code sur mon projet, le message d'avertissement suivant s'affiche:

  

CA2002: Microsoft.Reliability: 'SynchronizationForm.SynchronizationForm_Shown (object, EventArgs)' se verrouille sur une référence de type 'Type'. Remplacez-le par un verrou sur un objet à identité forte.

Quelqu'un peut-il m'expliquer ce qui ne va pas dans mon code et comment puis-je l'améliorer pour éliminer cet avertissement? Qu'est-ce que cela signifie que cet objet a une identité forte?

Était-ce utile?

La solution

Ce qui ne va pas, c'est que vous verrouillez quelque chose de public ( typeof (SynchronizationForm) ) qui est accessible partout à partir de votre code et si un autre thread se verrouille sur cette même chose, vous obtenez un blocage. En règle générale, il est conseillé de ne verrouiller que les objets statiques privés:

private static object _syncRoot = new object();
...
lock (_syncRoot) 
{

}

Cela vous garantit que seul le SynchronizationForm peut posséder le verrou.

Autres conseils

Extrait de la explication de la règle par MSDN

  

Un objet est dit avoir une identité faible lorsqu'il est directement accessible au-delà des limites du domaine d'application. Un thread qui essaie d'acquérir un verrou sur un objet ayant une identité faible peut être bloqué par un deuxième thread dans un domaine d'application différent disposant d'un verrou sur le même objet.

Etant donné que vous ne pouvez pas nécessairement prédire quels verrous un autre AppDomain peut prendre, et que de tels verrous peuvent nécessiter d'être organisés et qu'ils seraient alors coûteux, cette règle me semble logique.

Le problème est que typeof (SynchronizationForm) n'est pas un objet de verrouillage privé, ce qui signifie que tout autre élément de code pourrait l'utiliser pour se verrouiller, ce qui pourrait entraîner un blocage. Par exemple, si un autre code faisait ceci:

var form = new SynchronizationForm();
lock(typeof(SynchronizationForm))
{
    form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
}

Alors l'impasse se produira. Au lieu de cela, vous devez supprimer un objet de verrouillage privé dans la classe SynchronizationForm et le verrouiller à la place.

  

L'objet System.Type d'une classe peut facilement être utilisé comme verrou d'exclusion mutuelle pour les méthodes statiques de la classe.

Source: http://msdn.microsoft. com / fr-us / library / aa664735 (VS.71) .aspx

Pour ajouter à la réponse de Doug, vous avez ici un mécanisme de verrouillage qui ne devrait être utilisé que dans les méthodes statiques, et utilisé dans une méthode d'instance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top