Ma solution C# WinForm contient plusieurs projets dont un projet Admin contenant frmAdmin et un projet utilisateur contenant frmUser. Un troisième projet contient frmTimer qui a une minuterie qui lance périodiquement frmUser.Mutex non libéré
Je souhaite que frmTimer ne lance pas frmUser lorsque frmAdmin est ouvert.
J'utilise un mutex nommé pour indiquer à frmTimer si frmAdmin est ouvert; cependant, le mutex ne semble pas être libéré après la fermeture de frmAdmin.
Le mutex est créé en frmAdmin avec le code comme ceci:
public partial class frmAdmin : Form
{
Mutex m;
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
m = new Mutex(true, "frmAdmin");
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
m.ReleaseMutex();
MessageBox.Show("Debug 1 -- In the frmAdmin ONCLOSED Event."); //test code
Debug.WriteLine("Debug 1 -- In the frmAdmin ONCLOSED Event."); //test code
}
public frmAdmin(string strPassedFromLogin)
{
InitializeComponent();
<<Code snipped>>
}
private void frmAdmin_FormClosing(object sender, FormClosingEventArgs e)
{
//Start _ Added
bool mutexSet = true;
try
{
Mutex.OpenExisting("frmAdmin");
MessageBox.Show("Debug 2 -- In the frmAdmin FORMCLOSING Event."); //test code
}
catch (WaitHandleCannotBeOpenedException)
{
mutexSet = false;
}
if (mutexSet)
{
base.OnClosed(e);
m.ReleaseMutex();
}
//End _ Added
Application.Exit();
}
<<Code snipped>>
}
Dans un premier temps, je n'ai pas code mutex dans la méthode frmAdmin_FormClosing (la seule méthode contenait la ligne Application.Exit()). J'ai ajouté le code mutex dans une tentative de libérer le mutex, mais il n'est toujours pas publié.
Le mutex est utilisé dans frmTimer comme ceci:
private void tmTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
bool adminIsOpen = true;
try
{
Mutex.OpenExisting("frmAdmin");
MessageBox.Show("Debug 3 -- Mutex exists: frmAdmin IS open."); //test code
}
catch (WaitHandleCannotBeOpenedException)
{
adminIsOpen = false;
MessageBox.Show("Debug 4 -- Mutex doesn't exists: frmAdmin is NOT open."); //test code
}
if (adminIsOpen == false)
{
//frmAdmin is closed; go ahead and open frmUser.
<<Code snipped>>
}
}
Quand je lance l'application, le messagebox avec le « Debug 4 » texte apparaît à chaque fois que les feux de la minuterie jusqu'à ce que j'ouvre frmAdmin (frmAdmin est lancé à partir frmLogin après la vérification du mot de passe), à partir de ce moment-là, la boîte de message avec le texte 'Debug 3' apparaît chaque fois que la minuterie se déclenche, même après avoir quitté frmAdmin. Lorsque je quitte frmAdmin, je vois la boîte de message avec le texte 'Debug 2'. Je n'ai jamais vu le messagebox (ou un message de fenêtre de sortie) avec le texte 'Debug 1'.
Il semble que le mutex ne se libère pas après la fermeture de frmAdmin, ce qui empêche le lancement de frmUser.
Toute aide est appréciée.
Ceci est une question de suivi à this question.
MISE À JOUR
Voici mon code après avoir à travailler. Je l'ai eu à travailler en raison des réponses de Hans Passant et Chris Taylor et de Serhio de this post.
Le mutex est créé en frmAdmin avec le code comme ceci:
Mutex m;
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
m = new Mutex(true, "frmAdmin");
}
//This 'OnClosed' event is skipped when this application is terminated using only Exit(); therefore, call Close() before calling Exit().
//The 'catch' code is added to insure the program keeps running in the event these exceptions occur.
protected override void OnClosed(EventArgs e)
{
if (m != null)
{
try
{
base.OnClosed(e);
m.ReleaseMutex();
m.Close();
}
catch (AbandonedMutexException)
{
//This catch is included to insure the program keeps running in the event this exception occurs.
}
catch (ApplicationException)
{
//This catch is included to insure the program keeps running in the event this exception occurs.
}
catch (SynchronizationLockException)
{
//This catch is included to insure the program keeps running in the event this exception occurs.
}
}
}
Le mutex est utilisé dans frmTimer comme ceci:
private void tmTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
bool adminIsOpen = false;
Mutex _muty = null;
try
{
//If the named mutex does not exist then OpenExisting will throw the 'WaitHandleCannotBeOpenedException',
//otherwise the mutex exists and Admin is open.
_muty = Mutex.OpenExisting("frmAdmin");
adminIsOpen = true;
_muty.Close();
}
catch (WaitHandleCannotBeOpenedException)
{
//This catch is thrown when Admin is not opened (keep 'adminIsOpen = false'). Do not delete this catch.
}
catch (AbandonedMutexException)
{
//This catch is included to insure the program keeps running in the event this exception occurs.
}
if (adminIsOpen == false)
{
//frmAdmin is closed; go ahead and open frmUser.
<<Code snipped>>
}
}
Bonjour Hans, Merci d'avoir répondu. En guise de suivi, j'ai un autre mutex qui est utilisé pour s'assurer que l'application n'est lancée qu'une seule fois. Est-ce que cela affectera mon utilisation de WaitOnce (0)? Comment WaitOne (0) sait-il quel mutex rechercher? – Frederick
Ne pas ignorer la valeur de retour de Mutex.OpenExisting(), c'est le mutex que vous recherchez. En fait, la signalisation du mutex n'est pas nécessaire, juste l'existence suffit. Veillez à appeler la méthode Close(). Vérifiez ce fil: http://stackoverflow.com/questions/1904519/how-to-call-win32-createmutex-from-net –
pour suivre votre avertissement sur l'utilisation d'un événement Timer.Elapsed pour créer un nouveau formulaire: Si ma réponse est tout simplement changer: private void tmTimer_Elapsed (expéditeur d'objet, System.Timers.ElapsedEventArgs e) { à quelque chose comme ceci: private void timer1_Tick (expéditeur d'objet, System.EventArgs e) { Et puis ajoutez également ces deux lignes: private System.Windows.Form.Timer timer1; this.timer1.Tick + = new System.EventHandler (this.timer1_Tick); Si la réponse est complexe, je peux la poster comme une nouvelle question. – Frederick