2011-08-24 8 views
9

Normalmente veo estas dos piezas de código por todas partes. Ambas cosas también funcionan en mi caso, pero ¿a quién debo adherirme?¿Cuál de las siguientes expresiones Mutex previene idealmente múltiples instancias de la aplicación .Net y cuál es la diferencia?

Caso 1:

bool isNew = false; 
Mutex mutex = new Mutex(true, "MyApp_Mutex", out isNew); 
if (!isNew) 
{ 
    MessageBox.Show("already running.", "Multiple Instances Not Allowed", 
             MessageBoxButtons.OK, 
             MessageBoxIcon.Exclamation); 
    return; 
} 

Caso 2:

Mutex mutex = new Mutex(false, "MyApp_Mutex"))    
if (!mutex.WaitOne(0, false)) 
{ 
    MessageBox.Show("already running.", "Multiple Instances Not Allowed", 
             MessageBoxButtons.OK, 
             MessageBoxIcon.Exclamation); 
    return; 
} 
  1. ¿Cuál es la forma ideal entre los dos para evitar que varias instancias?

  2. ¿Cuál es la diferencia?

  3. Por otra parte veo como estos códigos:

    //if not return{ 
    mutex.ReleaseMutex(); 
    GC.Collect(); 
    //application.Run(); 
    GC.KeepAlive(mutex); 
    

bajo el segundo método, pero nunca con la primera. ¿Por qué es así? ¿O me equivoqué?

Básicamente se trata de la comprensión adecuada de los parámetros y métodos utilizados. Apreciaría si alguien puede detallarlo brevemente, no entiendo ni la mitad al leer la documentación de msdn ...

Respuesta

8

En el primer caso, le está pidiendo al sistema operativo que cree el mutex y le dé su propiedad si se crea - esto se realiza a través del primer parámetro, initiallyOwned. El parámetro isNew le dice si fue o no un nuevo mutex. Si es nuevo, se garantiza que es el propietario, ya que eso es lo que solicitó con el parámetro initiallyOwned. Como es nuevo y lo posee, sabe que no hay otras instancias de la aplicación en ejecución, porque si las hubiera, ya habrían creado el mutex y lo tendrían.

El segundo caso es básicamente lo mismo, pero hecho de una manera ligeramente diferente. No solicita la propiedad en la creación, pero en la llamada WaitOne. WaitOne solicita la propiedad y espera 0 milisegundos. Si obtiene la propiedad, entonces sabe que no se está ejecutando ninguna otra instancia de su aplicación, por las mismas razones que el caso 1.

En cuanto a qué usar, que yo sepa no importa. El primero parece ser más intuitivo, al menos para mí.

Adición respuesta a la pregunta # 3 nueva

Cuando la aplicación está completa se debe liberar el mutex ya que lo posee. Es probable que .NET lo libere cuando finalice su aplicación, pero es una buena práctica hacerlo. GC.Collect y GC.KeepAlive se ocupan de la recolección de basura. No puedo pensar en ningún escenario por qué estas llamadas serían necesarias cuando se trata de los mutexes que controlan el inicio. Declaro que mi exclusión mutua es estático, por lo que siempre estará dentro del alcance y no será liberado por el recolector de basura mientras dure mi aplicación.

+0

Gracias. Encuentro el primero en ser más elegante .. – nawfal

+0

Tengo una duda más que añadiré a la pregunta. Sería de gran ayuda si puedes ver eso. – nawfal

+0

Sí, me suena lógico. – nawfal

3

Para entender lo que está sucediendo en estas declaraciones, uno debe comprender qué es un mutex y cómo funcionan. No entraré en detalles importantes, pero los señalaré a este reference book. Lea los primeros capítulos hasta llegar a la sección sobre Mutexes.

La declaración de Mutex en su primer fragmento de código usa el bool isNew para especificar que la instancia actual de la aplicación fue la primera en ejecutarse, así como la primera instancia para crear el Mutex. Esto significa que se puede informar a cada ejecución secundaria de su aplicación que su identificador para Mutex en todo el sistema no fue el primero en crear y acceder al Mutex.

El siguiente bloque if comprueba si la tarea asociada fue la primera en señalar al Mutex y luego maneja el estado en consecuencia.

El segundo fragmento de código es completamente diferente. Se puede usar un Mutex en una tarea (tarea B) para esperar otra tarea (tarea A) para indicar al Mutex que cualquier otra tarea (tarea B) puede continuar.

El método WaitOne(secs, releaseConext) está diciendo, esperar a que el objeto mutex para enviar una respuesta de señal para X segundos si está bloqueado por otro subproceso. Si el método no obtiene una respuesta de señal en X segundos, devuelve false y, en el caso de su código de muestra, ingresa el bloque if que se utiliza para cerrar la aplicación.

Personalmente, usaría el primer fragmento de código. Me imagino que ambos operan con la misma cantidad de gastos generales. Sin embargo, al elegir qué versión usar, consideraría que el primer método es el mejor para usar como práctica general.

+0

¡gran explicación! – nawfal

+0

Tengo una duda más que añadiré a la pregunta – nawfal

+0

Lo siento, no pude responder a su pregunta adicional actualizada (n. ° 3) antes de C.C.G. respondido Él ha clavado la respuesta en la cabeza. Sí, el código adicional se considera una "buena práctica", pero el GC se ha optimizado bien en los últimos 10 años y nunca he encontrado la necesidad de tener dicho código. +1 a CCG. – RLH

Cuestiones relacionadas