Domanda

Nella mia applicazione ho un modulo che avvia il processo di sincronizzazione e per diversi motivi voglio consentire l'esecuzione di una sola sincronizzazione alla volta. Quindi ho aggiunto un campo bool statico al mio modulo indicando se la sincronizzazione è in corso e ho aggiunto un blocco per impostare questo campo su true se non era già impostato in modo che il primo thread potesse iniziare la sincronizzazione ma quando è in esecuzione ogni altro thread che proverà ad avviarlo terminerà.

Il mio codice è qualcosa del genere:

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();
            }
        }
    }
}

Funziona bene ma quando eseguo Analisi del codice sul mio progetto ricevo il seguente messaggio di avviso:

  

CA2002: Microsoft.Reliability: 'SynchronizationForm.SynchronizationForm_Shown (object, EventArgs)' si blocca su un riferimento di tipo 'Tipo'. Sostituiscilo con un lucchetto contro un oggetto con identità forte.

Qualcuno può spiegarmi cosa c'è che non va nel mio codice e come posso migliorarlo per eliminare l'avviso. Cosa significa che l'oggetto ha un'identità forte?

È stato utile?

Soluzione

Ciò che è sbagliato è che stai bloccando qualcosa di pubblico ( typeof (SynchronizationForm) ) che è accessibile ovunque dal tuo codice e se qualche altro thread si blocca su questa stessa cosa ottieni un deadlock. In generale è una buona idea bloccare solo su oggetti statici privati:

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

}

Questo ti garantisce che solo il SynchronizationForm può possedere il blocco.

Altri suggerimenti

Dalla spiegazione MSDN della regola

  

Si dice che un oggetto ha un'identità debole quando è possibile accedervi direttamente attraverso i confini del dominio dell'applicazione. Un thread che tenta di acquisire un blocco su un oggetto con un'identità debole può essere bloccato da un secondo thread in un dominio dell'applicazione diverso che ha un blocco sullo stesso oggetto.

Dal momento che non puoi necessariamente prevedere quali blocchi potrebbe richiedere un altro AppDomain e poiché potrebbe essere necessario eseguire il marshalling di tali blocchi e sarebbe quindi costoso, questa regola ha senso per me.

Il problema è che typeof (SynchronizationForm) non è un oggetto di blocco privato, il che significa che qualsiasi altro pezzo di codice potrebbe usarlo per bloccare, il che potrebbe causare deadlock. Ad esempio se un altro codice ha fatto questo:

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

Quindi si verificherà un deadlock. Invece dovresti eliminare un oggetto di blocco privato nella classe SynchronizationForm e bloccarlo invece.

  

L'oggetto System.Type di una classe può essere comodamente utilizzato come blocco di mutua esclusione per i metodi statici della classe.

Fonte: http://msdn.microsoft. com / it-it / library / aa664735 (VS.71) aspx

Per aggiungere alla risposta di Doug, quello che hai qui è un meccanismo di blocco che dovrebbe essere usato solo in metodi statici, usato in un metodo di istanza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top