Pregunta

Tengo este síngleton objeto de caché y se expone un IEnumerable propiedad que simplemente devuelve un privado IEnumerable variable.

Tengo un método estático en mi objeto singleton que las actualizaciones de esta variable miembro (que existe en el single 'Instancia' instancia de este objeto de caché).

Digamos que algunos de hilo es actualmente la iteración sobre este IEnumerable variable de la propiedad, mientras que mi memoria caché es la actualización.Lo hice así para que la caché se actualiza en una nueva variable local y, finalmente, la configuración de los expuestos variable privada a punto para esta nueva variable local.

Sé que estoy solo actualizar una referencia, dejando a los otros (de edad) objeto en la memoria, esperando a ser recogido por la GC, pero mi problema es - no estoy 100% seguro de lo que sucede una vez que establezca la nueva referencia?Sería el otro hilo de repente se itera sobre el nuevo objeto o el viejo se pasó a través de la interfaz IEnumerable?Si hubiera sido una referencia normal, yo diría 'no'.El subproceso de llamada estaría operando en el objeto viejo, pero no estoy seguro de si este es el caso de IEnumerable así?

Esta es la clase despojado:

internal sealed class SektionCache : CacheBase
{
    public static readonly SektionCache Instance = new SektionCache();
    private static readonly object lockObject = new object();
    private static bool isUpdating;

    private IEnumerable<Sektion> sektioner;

    static SektionCache()
    {
        UpdateCache();
    }

    public IEnumerable<Sektion> Sektioner
    {
        get { return sektioner; }
    }

    public static void UpdateCache()
    {
    // SNIP - getting data, locking etc.
    Instance.sektioner = newSektioner;
    // SNIP
    }
}
¿Fue útil?

Solución

El hilo que actualmente es la enumeración de sektioner seguirá enumerar incluso cuando se actualiza la referencia dentro del singleton.No hay nada especial acerca de los objetos que implementan la interfaz IEnumerable.

Usted tal vez debería añadir la volátiles la palabra clave para el sektioner campo como no proporcionar lectura y de bloqueo de múltiples hilos son de lectura/escritura de la misma.

Otros consejos

Desde el getter { return sektioner; } se llama antes de que el nuevo valor es poner en el campo, el valor anterior se devuelve.Entonces, el bucle foreach (Sektion s in cache.Sektioner) utiliza el valor que se recibe cuando el captador fue llamado, es decir,el valor antiguo.Ese valor será utilizado durante todo el bucle foreach.

Primero de todo yo no puede ver el objeto de bloqueo, sin usar lockObject variable me hace triste.IEnumerable no es especial.Cada hilo tiene su propia copia de la referencia a alguna instancia de sektioner objeto.Usted no puede afectar a otros hilos de esa manera.¿Qué pasaría con la versión antigua de datos apuntados por sektioner campo depende en gran medida de persona que llama.

Creo que, si usted quiere un hilo de seguridad, usted debe utilizar de esta manera:

internal sealed class SektionCache : CacheBase
{
    //public static readonly SektionCache Instance = new SektionCache();

    // this template is better ( safer ) than the previous one, for thread-safe singleton patter >>>
    private static SektionCache defaultInstance;
    private static object readonly lockObject = new object();
    public static SektionCach Default {
        get {
            SektionCach result = defaultInstance;
            if ( null == result ) {
                lock( lockObject ) {
                    if ( null == result ) {
                        defaultInstance = result = new SektionCache();
                    }
                }
            }

            return result;
        }
    }
    // <<< this template is better ( safer ) than the previous one

    //private static readonly object lockObject = new object();
    //private static bool isUpdating;
    //private IEnumerable<Sektion> sektioner;

    // this declaration is enough
    private volatile IEnumerable<Sektion> sektioner;

    // no static constructor is required >>>
    //static SektionCache()
    //{
    //    UpdateCache();
    //}
    // <<< no static constructor is required

    // I think, you can use getter and setter for reading & changing a collection
    public IEnumerable<Sektion> Sektioner {
        get {
            IEnumerable<Sektion> result = this.sektioner;
            // i don't know, if you need this functionality >>>
            // if ( null == result ) { result = new Sektion[0]; }
            // <<< i don't know, if you need this functionality
            return result;
        }
        set { this.sektion = value; }
    }

    //public static void UpdateCache()
    //{
    //// SNIP - getting data, locking etc.
    //Instance.sektioner = newSektioner;
    //// SNIP
    //}
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top