Domanda

namespace MyNameSpace
{
    static class MyClass
    {
        static MyClass()
        {
            //Authentication process.. User needs to enter password
        }

        public static void MyMethod()
        {
            //Depends on successful completion of constructor
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.MyMethod();
        }
    }
}

Ecco la sequenza che ho ipotizzato

  1. Inizio del costruttore statico
  2. Fine del costruttore statico
  3. Inizio del main
  4. Inizio di MyMethod
  5. Fine del main

Ora, in qualsiasi scenario, se 4 inizierà prima del 2, sono fregato.È possibile?

È stato utile?

Soluzione

Hai posto solo una domanda qui, ma ci sono una dozzina circa di domande che avresti dovuto porre, quindi risponderò a tutte.

Ecco la sequenza che ho ipotizzato

  1. Inizio del costruttore di classi (noto anche come cctor)
  2. Fine del cctor
  3. inizio di Main
  4. inizio di MyMethod

È corretto?

No. La sequenza corretta è:

  1. Avvio del cctor per il programma, se presente. Non c'è.
  2. Fine del cctor per il programma, se presente. Non c'è.
  3. Inizio di Main
  4. Avvio di cctor per MyClass
  5. Fine del cctor per MyClass
  6. Inizio di MyClass.MyMethod

E se esiste un inizializzatore di campo statico?

Il CLR può modificare l'ordine in cui vengono eseguiti gli inizializzatori di campo statico in alcuni casi. Vedi la pagina di Jon sull'argomento per i dettagli:

Le differenze tra costruttori statici e inizializzatori di tipo

È mai possibile che un metodo statico come MyMethod venga chiamato prima del completamento del cctor di quella classe?

Sì. Se il cctor stesso chiama MyMethod, ovviamente MyMethod verrà chiamato prima del completamento del cctor.

Il cctor non chiama MyMethod. È mai possibile che un metodo statico come MyMethod venga chiamato prima del completamento del cctor di MyClass?

Sì. Se il cctor utilizza un altro tipo il cui cctor chiama MyMethod, MyMethod verrà chiamato prima del completamento del cctor MyClass.

Nessun cctor chiama MyMethod, direttamente o indirettamente! Ora è mai possibile che un metodo statico come MyMethod venga chiamato prima che il cctor di MyClass sia completato?

No.

È ancora vero anche se sono coinvolti più thread?

Sì. Il cctor terminerà su un thread prima che il metodo statico possa essere chiamato su qualsiasi thread.

Il cctor può essere chiamato più di una volta? Supponiamo che due thread causino entrambi l'esecuzione del cctor.

È garantito che il cctor venga chiamato al massimo una volta, indipendentemente dal numero di thread coinvolti. Se due thread chiamano MyMethod "contemporaneamente", corrono. Uno di loro perde la gara e si blocca finché il cctor MyClass non termina sul thread vincente.

Il thread perdente si blocca finché il cctor non è terminato? Davvero ?

Davvero.

Quindi cosa succede se il cctor sul thread vincente chiama codice che si blocca su un blocco precedentemente preso dal thread perdente ?

Quindi hai una classica condizione di inversione dell'ordine di blocco. Il tuo programma si blocca. Per sempre.

Sembra pericoloso. Come posso evitare il deadlock?

Se fa male quando lo fai, smetti di farlo . Non fare mai qualcosa che possa bloccarsi in un cctor.

È una buona idea fare affidamento sulla semantica di inizializzazione del cctor per applicare requisiti di sicurezza complessi? Ed è una buona idea avere un cctor che esegue le interazioni con gli utenti?

Nemmeno le buone idee. Il mio consiglio è che dovresti trovare un modo diverso per assicurarti che le condizioni preliminari che influiscono sulla sicurezza dei tuoi metodi siano soddisfatte.

Altri suggerimenti

Secondo MSDN , un costruttore statico:

Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima della creazione della prima istanza o di eventuali membri statici referenziato.

Quindi il costruttore statico verrà chiamato prima che venga invocato il metodo statico MyClass.MyMethod() (supponendo che non sia anche invocato durante la costruzione statica o l'inizializzazione del campo statico, ovviamente).

Ora, se stai facendo qualcosa di asincrono in quel static constructor, è compito tuo sincronizzarlo.

Il n. 3 è in realtà il n. 1: l'inizializzazione statica non si avvia fino al primo utilizzo della classe a cui appartiene.

È possibile se MyMethod viene chiamato dal costruttore statico o da un blocco di inizializzazione statico.Se non invochi MyMethod direttamente o indirettamente dal tuo costruttore statico, dovresti stare bene.

Dalla documentazione (enfasi mia):

Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima della creazione della prima istanza o di eventuali membri statici referenziato .

Puoi garantire che 4 verrà sempre dopo 2 (se non crei un'istanza della tua classe dal tuo metodo statico), tuttavia lo stesso non è vero per 1 e 3.

Il costruttore statico verrà chiamato prima dell'esecuzione di mymethod.Tuttavia, se sei fregato se 4 viene chiamato prima del 2, ti suggerisco di ripensare al tuo design.Non dovrebbe comunque fare cose complicate in un costruttore statico.

CLR garantisce che il costruttore statico venga eseguito prima dell'accesso a qualsiasi membro statico.Tuttavia, il tuo design è un po 'puzzolente.Sarebbe più semplice fare qualcosa del genere:

static void Main(string[] args) 
{ 
     bool userIsAuthenticated = MyClass.AuthenticateUser();
     if (userIsAuthenticated)
         MyClass.MyMethod(); 
 } 

Con la tua progettazione, se l'autenticazione fallisce, l'unico modo per impedire l'esecuzione di MyMethod è lanciare un'eccezione.

È garantito che il costruttore di una classe statica sia stato chiamato prima che uno qualsiasi dei suoi metodi venga eseguito.Esempio:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press enter");
        Console.ReadLine();
        Boop.SayHi();
        Boop.SayHi();
        Console.ReadLine();
    }

}

static class Boop
{
    static Boop()
    {
        Console.WriteLine("Hi incoming ...");
    }

    public static void SayHi()
    {
        Console.WriteLine("Hi there!");
    }
}

Risultato:

Premi invio

// dopo aver premuto invio

Salve in arrivo ...

Salve!

Salve!

Ecco l'ordine effettivo in cui le cose vanno giù:

  1. Inizio di Main
  2. Inizio del costruttore statico MyClass
  3. Fine del costruttore statico MyClass
  4. Inizio di MyMethod
  5. Fine del Main

Oppure puoi eseguire il debugger.

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