My c # WinForm решение содержит несколько проектов, включая проект Admin, содержащий frmAdmin, и проект User, содержащий frmUser. Третий проект содержит frmTimer с таймером, который периодически запускает frmUser.
Я хочу, чтобы frmTimer не запускал frmUser при открытом frmAdmin.
Я использую именованный мьютекс, чтобы сообщить frmTimer, открыт ли frmAdmin; однако мьютекс, по-видимому, не освобождается после закрытия frmAdmin.
Мьютекс создается в frmAdmin с кодом, подобным следующему:
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>>
}
Изначально у меня не было никакого кода мьютекса в методе frmAdmin_FormClosing (метод содержал только строку Application.Exit ()). Я добавил код мьютекса в попытке освободить мьютекс, но он все еще не освобождается.
Мьютекс используется в frmTimer следующим образом:
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>>
}
}
Когда я запускаю приложение, окно сообщения с текстом «Отладка 4» появляется каждый раз, когда запускается таймер, пока я не открою frmAdmin (frmAdmin запускается из frmLogin после проверки пароля), с этого момента в окне сообщения с «Отладка 3» Текст появляется каждый раз, когда срабатывает таймер, даже после того, как я выйду из frmAdmin. При выходе из frmAdmin я вижу окно сообщения с текстом «Отладка 2». Я никогда не видел окно сообщения (или сообщение окна вывода) с текстом «Отладка 1».
Похоже, что мьютекс не освобождается после закрытия frmAdmin, и это препятствует запуску frmUser.
Любая помощь приветствуется.
Это дополнительный вопрос к этому вопросу.
UPDATE
Вот мой код после того, как он заработал. Я получил его на работу из-за ответов Ганса Пассанта и Криса Тейлора и Серхио из этой записи.
Теперь мьютекс создается в frmAdmin с кодом, подобным следующему:
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.
}
}
}
Мьютекс используется в frmTimer следующим образом:
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>>
}
}