My c# WinForm solution contains several projects including an Admin project containing frmAdmin and a User project containing frmUser. A third project contains frmTimer that has a timer that periodically launches frmUser.
I want frmTimer to not launch frmUser when frmAdmin is open.
I'm using a named mutex to tell frmTimer if frmAdmin is open; however, the mutex appears not to be released after frmAdmin is closed.
The mutex is created in frmAdmin with code like this:
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>>
}
Initially, I did not have any mutex code in the frmAdmin_FormClosing method (the method only contained the Application.Exit() line). I added the mutex code in an attempt to release the mutex, but it is still not being released.
The mutex is used in frmTimer like this:
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>>
}
}
When I run the application, the messagebox with the 'Debug 4' text appears each time the timer fires until I open frmAdmin (frmAdmin is launched from frmLogin after password verification), from then on the messagebox with the 'Debug 3' text appears each time the timer fires, even after I exit frmAdmin. When exiting frmAdmin, I see the messagebox with the 'Debug 2' text. I've never seen the messagebox (or an output window message) with the 'Debug 1' text.
It appears as though the mutex doesn't release after frmAdmin is closed and this prevents frmUser from launching.
Any help is appreciated.
This is a follow-up question to this question.
UPDATE
Here is my code after getting it to work. I got it to work because of the answers from Hans Passant and Chris Taylor and from Serhio from this post.
The mutex is now created in frmAdmin with code like this:
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.
}
}
}
The mutex is used in frmTimer like this:
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>>
}
}