我的 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”文本的消息框。我从未见过带有“调试 1”文本的消息框(或输出窗口消息)。
看起来好像在 frmAdmin 关闭后互斥体没有释放,这会阻止 frmUser 启动。
任何帮助表示赞赏。
这是一个后续问题this问题。
UPDATE
这是我让它工作后的代码。我之所以能成功,是因为 Hans Passant 和 Chris Taylor 以及 Serhio 的回答this post.
现在,互斥锁已在 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>>
}
}