【发布时间】:2011-03-17 13:46:36
【问题描述】:
我的 c# WinForm 解决方案包含多个项目,包括一个包含 frmAdmin 的管理项目和一个包含 frmUser 的用户项目。第三个项目包含 frmTimer,它有一个定期启动 frmUser 的计时器。
我希望 frmTimer 在打开 frmAdmin 时不启动 frmUser。
我正在使用一个命名的互斥锁来告诉 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(密码验证后从 frmLogin 启动 frmAdmin),然后在带有“调试 3”的消息框上每次计时器触发时都会出现文本,即使在我退出 frmAdmin 之后也是如此。退出 frmAdmin 时,我看到带有“调试 2”文本的消息框。我从未见过带有“Debug 1”文本的消息框(或输出窗口消息)。
看起来好像在 frmAdmin 关闭后互斥锁没有释放,这会阻止 frmUser 启动。
感谢任何帮助。
这是this 问题的后续问题。
更新
这是我运行后的代码。由于 Hans Passant 和 Chris Taylor 以及来自 this 帖子的 Serhio 的回答,我得到了它的工作。
现在在 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>>
}
}
【问题讨论】: