He estado utilizando este patrón para inicializar datos estáticos en mis clases. Parece seguro para mí, pero sé lo sutiles que pueden ser los problemas de enhebrado. Aquí está el código:Inicialización segura de subprocesos de variables estáticas
public class MyClass // bad code, do not use
{
static string _myResource = "";
static volatile bool _init = false;
public MyClass()
{
if (_init == true) return;
lock (_myResource)
{
if (_init == true) return;
Thread.Sleep(3000); // some operation that takes a long time
_myResource = "Hello World";
_init = true;
}
}
public string MyResource { get { return _myResource; } }
}
¿Hay algún agujero aquí? Tal vez hay una manera más simple de hacer esto.
ACTUALIZACIÓN: El consenso parece ser que un constructor estático es el camino a seguir. Se me ocurrió la siguiente versión usando un constructor estático.
public class MyClass
{
static MyClass() // a static constructor
{
Thread.Sleep(3000); // some operation that takes a long time
_myResource = "Hello World";
}
static string _myResource = null;
public MyClass() { LocalString = "Act locally"; } // an instance constructor
// use but don't modify
public bool MyResourceReady { get { return _myResource != null; } }
public string LocalString { get; set; }
}
Espero que esto sea mejor.
@RaoulRobin, un constructor estático estaría en orden, pero solo si quiere una clase estática. Si no desea compartir sus campos en todas las instancias de MyClass, debe emplear una sincronización adecuada. – Kiril
En la versión de la vida real, el recurso estático es Dictionary <> que se carga previamente, que se lee simultáneamente en varias instancias de la clase. MSDN dice que las lecturas concurrentes están bien siempre que el Diccionario no se modifique durante las lecturas. Gracias por el comentario. – RaoulRubin