2012-06-28 12 views
9

Recientemente tuve algunos problemas con una clase de singelton que era perezoso al inicializar un diccionario donde un segundo hilo intentaba usarlo antes de que realmente se hubiera rellenado. Así que implementé la inicialización de la variable a través de la clase Lazy<T>.¿Está usando Lazy <T> malo para el rendimiento?

Aquí está mi código:

private static Dictionary<string, string> GroupDefaults 
{ 
    get { return mGroupDefaults.Value; } 
} 
private static Lazy<Dictionary<string, string>> mGroupDefaults = 
    new Lazy<Dictionary<string,string>>(delegate 
    { 
     Dictionary<string, string> defaults = new Dictionary<string, string>(); 
     foreach (KeyValuePair<string, UnitGroup> groupDef in Groups) 
      defaults.Add(groupDef.Key, groupDef.Value.First().Key); 
     return defaults; 
    }); 

que esto esté arreglado el problema y ahora estoy considerando hacer de esto una práctica regular de la mina para utilizar la clase Lazy<T> en cualquier lugar que hago inicialización lenta para evitar posibles problemas de threads. Entonces, básicamente, me gustaría saber si esta es una buena/práctica común. ¿O será detremental para el rendimiento o algo así?

Respuesta

10

Es bastante difícil de decir sin saber qué tipo de restricciones de rendimiento tiene, pero en mi experiencia, la inicialización rara vez es un cuello de botella (ya que por definición solo ocurre una vez) Lazy<T> se escribió para proporcionarle este servicio exacto, entonces recomendaría usarlo.

+0

¿Es una buena práctica usar la clase Lazy ? –

+2

@ AlexHopeO'Connor ¡Es por eso que fue agregado! La desventaja de usar la clase es que la declaración del campo/propiedad se vuelve un poco más desordenada (como se puede ver) pero en términos de rendimiento, es sólida. – dlev

+2

Eso es todo lo que necesitaba escuchar, es solo que no he visto muchos ejemplos de él en el código de otras personas. –

1

Creo que puede estar utilizando Lazy para su uso no previsto. Lazy se debe usar para situaciones en las que algo tiene un gran costo de inicialización, pero existe la posibilidad de que no se use durante la vida del objeto.

Si siempre a GroupDefaults al menos una vez por su vida útil un método mejor sería para inicializar GroupDefaults en un subproceso en segundo plano en el inicio de la vida del envase y la esperanza de que se haga antes de que se realiza la inicialización (Sé que hay una clase para esto, pero necesito profundizar en el MSDN para encontrarlo)

+1

Aunque estoy de acuerdo en que es el caso de uso previsto, * también * implementa la inicialización segura de subprocesos correctamente, por lo que no tienes que preocuparte sobre hacerlo tú mismo. – dlev

+0

Lo estaba inicializando desde otro subproceso, sin embargo, la inicialización no se completó antes de que otras cosas cargadas lado a lado intentaran acceder a ella. Es una situación muy extraña en la que no puedo cargar de forma secuencial, ya que agregaría una buena cantidad de tiempo para cargar los tiempos. Así que estoy generando una cantidad de hilos que hacen una buena cantidad de trabajo antes de que se detengan debido a que los GroupDefaults no se han inicializado, lo que da como resultado tiempos de carga más rápidos. Sin embargo, básicamente estoy preguntando ¿cuál sería el efecto negativo de usar esta clase? ¿Cuáles son sus lados negativos? –

2

Si esto es para un singleton, un static constructor podría ser lo que desea. Algo así como:

class MySingleton 
{ 
    static MySingleton() 
    { 
     Instance().InitDict(); 
    } 
} 
3

De la documentación, encuentro lo siguiente:

Si ningún delegado se pasa en el constructor perezoso, el tipo envuelta se crea mediante el uso de Activator.CreateInstance cuando el valor de la propiedad primero se accede. Si el tipo no tiene un constructor predeterminado, se lanza una excepción en tiempo de ejecución.

Activator.CreateInstance es un método que es notoriamente malo para el rendimiento. Sin embargo, eso no parece ser un problema en su caso, y en cualquier caso, como dijo dlev, invocar el método una vez no sería un problema. No he visto Lazy<T> usado muy a menudo, pero no veo ninguna razón para no usarlo en su caso.

Cuestiones relacionadas