Pregunta

Tengo un archivo que se lee y se escribe en. Necesito asegurarme de cuándo se ha escrito, nadie más intentará escribirle.

Puse un candado en toda la función que permite leer o escribir, pero todavía tengo errores como El proceso no puede acceder al archivo "NOMBRE DE ARCHIVO" porque está siendo usado por otro proceso.

public static TYPE Property{

get{
    data mydata;
    Object obj = new object();
    Monitor.Enter(obj);

    // check if data has not changed
    // if it has not, just read

    using (Stream stream = File.Open(fileLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
        //....
    }
    // else, if data changed, then need to write to  file to save the new data

    using (Stream stream = File.Open(fileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) {
        BinaryFormatter bf = new BinaryFormatter();

        try {
            bf.Serialize(stream, (data);
        }
        //DONE processing

        Monitor.Pulse(obj);
        Monitor.Exit(obj);
        return data
}
¿Fue útil?

Solución

Está creando un monitor nuevo para bloquear cada vez que se invoca la propiedad. Debe bloquear el mismo monitor, de lo contrario no tiene sentido bloquearlo.

También deberías usar un " bloqueo " declaración: nunca estás esperando, así que no tiene sentido pulsar. Actualmente, si se producen excepciones, terminará con " fugas " La cerradura. Normalmente, ese sería un problema realmente grave, pero como de todos modos no estás reutilizando el bloqueo, eso está ocultando el problema.

Por ejemplo:

private static readonly object monitor = new object();

public static TYPE Property
{
    get
    {
        lock(monitor)
        {
            // check if data has not changed
            // if it has not, just read
            using (Stream stream = File.Open(fileLocation, 
                   FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                ....
            }
            // else, if data changed, then need to write to 
            // file to save the new data
            using (Stream stream = File.Open
                       (fileLocation, FileMode.OpenOrCreate,
                        FileAccess.ReadWrite, FileShare.Read))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(stream, data);
            }
            return data;
        }
    }
}

Además, parece que está haciendo más trabajo del que realmente esperaría en una propiedad. ¿Estás seguro de que un método no tendría más sentido?

Otros consejos

Bueno, Monitor. Ingrese bloquea el acceso de cualquier subproceso que intenta colocar un bloqueo en EL MISMO objeto. Cada vez que ingresas a tu captador, creas un nuevo objeto, por lo que cada persona que llama recibe un nuevo bloqueo que no sabe nada entre sí.

En otras palabras, no hay bloqueo.

como nota al margen: ¿por qué no usa la instrucción de bloqueo? Aún necesitarás un objeto de bloqueo global.

El motivo de la variable global en comparación con su variable local es que el BLOQUEO está bloqueando un punto de referencia en la memoria como lo entiendo. Cada vez que crea una instancia de un nuevo objeto, es decir, " Object obj = new object (); " ;, está creando un nuevo objeto, con su propio puntero único en la memoria. Así que cuando LOCK mira para ver si el punto en la memoria está bloqueado, no lo está. Porque es un nuevo punto de referencia en la memoria y el único que lo usa es la persona que llama que ingresa a su propiedad. Al tener su variable Obj declarada globalmente, siempre será el mismo punto en la memoria y el bloqueo puede validarse, de hecho, ese punto en la memoria está actualmente bloqueado o puede bloquearlo por sí mismo.

Ejemplo: (en bruto, pero creo que se entiende)

Object obj = new object ();

Ahora tienes un punto en la memoria que se parece bastante a:

Memoria -

    * obj1

ahora ingresas nuevamente a tu propiedad y creas un nuevo objeto nuevamente. La memoria de tu sistema ahora parece un poco ...

Memoria -

   * obj1
   * obj2

En el primer viaje, su bloqueo está marcando " Obj1 " en memoria. Dado que la persona que llama al 1er viaje a su propiedad es la única que usa esa instancia de Obj, es la única que lo bloquearía o revisaría para ver si está bloqueada. Porque está mirando esa copia de esa referencia de Obj en la memoria.

En el segundo viaje, su bloqueo es checkign " Obj2 " en memoria.

Cuando usa una variable global, ese punto en la memoria persiste, por lo que el bloqueo siempre verifica el mismo punto en la memoria. nunca se mueve y siempre es el mismo punto de referencia en la memoria. Por lo tanto, todas las personas que llaman a su propiedad siempre usarán el mismo punto de referencia en la memoria, su bloqueo tendrá éxito como espera.

Nota especial: no estoy indicando un tiempo de vida de " obj " ;. Simplemente estoy indicando cómo funciona esto en un proceso de múltiples subprocesos. Espero que ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top