2010-01-11 20 views
27

Así que aquí es un extracto de una de mis clases:¿Cómo puede ser nulo un campo estático de solo lectura?

[ThreadStatic] 
    readonly static private AccountManager _instance = new AccountManager(); 

    private AccountManager() 
    { 
    } 

    static public AccountManager Instance 
    { 
     get { return _instance; } 
    } 

Como se puede ver, es un hilo Singleton-per-- es decir, la instancia está marcado con el atributo ThreadStatic. La instancia también se instancia como parte de la construcción estática.

Entonces, siendo así, ¿cómo es posible que obtenga una NullReferenceException en mi aplicación ASP.NET MVC cuando trato de usar la propiedad Instancia?

+1

espectáculo en el que usted está tratando de usarlo, que puede ayudar, en el que el nullref está decayendo – curtisk

+0

Se trata de ser consumido en la aplicación ASP.NET de un envoltorio - pública IAccount Get (correo electrónico cadena) { retorno AccountManager .Ejemplo.Obtener (correo electrónico); } Esto podría ser más complicado de lo que pensaba; matar el servidor web (el incorporado en VS) y reiniciar la aplicación hizo que el problema desapareciera ... – gerrod

Respuesta

38

Citando MSDN ThreadStaticAttribute:

No especifique valores iniciales para campos marcados con ThreadStaticAttribute, porque tal inicialización se produce sólo una vez, cuando el constructor de la clase ejecuta y por lo tanto, afecta a un solo hilo. Si no se especifica un valor inicial, que puede confiar en el campo siendo inicializado a su valor por defecto si es un tipo de valor o de un valor nulo referencia (Nothing en Visual Basic) si es una referencia tipo.

+0

+1 por proporcionar la referencia –

+0

De acuerdo, he marcado esto como la respuesta. Gracias Austin! – gerrod

1

Creo que lo que está sucediendo es que el campo estático solo se inicializa una vez, entonces cuando otro hilo intenta leer el campo será nulo (ya que es el valor predeterminado) porque _instance no se puede inicializar nuevamente. Solo es un pensamiento, pero podría estar totalmente alejado, pero eso es lo que creo que está sucediendo.

12

Esta es una parte confusa del atributo ThreadStatic. Aunque crea un valor por hilo, el código de inicialización solo se ejecuta en uno de los hilos. Todos los otros subprocesos que acceden a este valor obtendrán el valor predeterminado para ese tipo en lugar del resultado del código de inicialización.

En lugar de inicializar el valor, envuélvalo en una propiedad que realice la inicialización por usted.

[ThreadStatic] 
readonly static private AccountManager _instance; 

private AccountManager() 
{ 
} 

static public AccountManager Instance 
{ 
    get 
    { 
    if (_instance == null) _instance = new AccountManager(); 
    return _instance; 
    } 
} 

Debido a que el valor _instance es único por hilo, no es necesario ningún bloqueo en la propiedad y que puede ser tratado como cualquier otro valor perezosamente inicializado.

+0

Gracias Jared; mi solución es muy similar a la tuya, pero no sabía eso sobre ThreadStatic. ¡Entonces engañame! – gerrod

8

Ha accedido a un clásico [ThreadStatic] "101" aquí.

El inicializador estático solamente se disparará una vez, a pesar de que se marca como [ThreadStatic], por lo demás hilos (aparte de la primera) verán esto no inicializado.

0

Un campo estático marcado con ThreadStaticAttribute no se comparte entre subprocesos. Cada hilo de ejecución tiene una instancia separada del campo, y establece y obtiene valores para ese campo de forma independiente. Si se accede al campo en un hilo diferente, contendrá un valor diferente.

Cuestiones relacionadas