互斥锁不能正常工作
本文关键字:工作 常工作 不能 | 更新日期: 2023-09-27 18:10:00
所以这段代码在program.cs中,应该检查连接是否可用,是否有另一个实例已经在运行。如果有,则消息框通知用户,并询问他是否确定要打开应用程序。下一个问题是:我打开应用程序,然后再打开它,显示消息框,但什么也没发生。我重复这个过程,只有在4-5次之后它才有效。然后,如果我再次打开,它会打开2个实例。
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SqlConnection con123 = new SqlConnection(con123.Metoda());
Mutex mut = null;
try
{
mut = Mutex.OpenExisting("Tray minimizer");
}
catch
{
}
if (mut == null)
{
mut = new Mutex(true, "Tray minimizer");
Application.Run(new Form1());
//Tell GC not to destroy mutex until the application is running and
//release the mutex when application exits.
GC.KeepAlive(mut);
mut.ReleaseMutex();
}
else
{
//The mutex existed so exit
mut.Close();
DialogResult result = MessageBox.Show("AApplication is already working!Do you want to reopen it?", "Caution!", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
foreach (Process p in System.Diagnostics.Process.GetProcessesByName("Name of application"))
{
try
{
p.Kill();
// p.WaitForExit(); // possibly with a timeout
Application.Run(new Form1());
}
catch (Win32Exception winException)
{
// process was terminating or can't be terminated - deal with it
}
catch (InvalidOperationException invalidException)
{
// process has already exited - might be able to let this one go
}
}
}
//if (result == DialogResult.Cancel)
//{
//}
}
try
{
con123.Open();
con123.Close();
}
catch
{
MessageBox.Show("Cant connect to server!!!", "Error!");
Application.Exit();
}
我会这样做:
bool mutexCreated = true;
using (Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
{
if (mutexCreated)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SqlConnection con123 = new SqlConnection(con123.Metoda());
Application.Run(new Form1());
}
else
{
DialogResult result =
MessageBox.Show("AApplication is already working!Do you want to reopen it?", "Caution!",
MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
foreach (Process p in System.Diagnostics.Process.GetProcessesByName("Name of application"))
{
try
{
p.Kill();
Application.Run(new Form1());
}
catch (Win32Exception winException)
{
// process was terminating or can't be terminated - deal with it
}
catch (InvalidOperationException invalidException)
{
// process has already exited - might be able to let this one go
}
}
}
}
try
{
con123.Open();
con123.Close();
}
catch
{
MessageBox.Show("Cant connect to server!!!", "Error!");
Application.Exit();
}
}
您的版本的问题是互斥锁可能在不适当的时间被收集。
-
一旦你结束在"互斥存在"的路径,你永远不会释放互斥。你只需要杀死其他进程并再次启动你的应用程序,但永远不会提供一种方法来释放互斥锁,当你的新应用程序结束时。
-
你在
foreach (Process)
循环中启动你的应用程序,这意味着如果有多个进程已经在运行(也许所有的消息框),你将为每个进程启动你的应用程序。 -
这也意味着你不会启动你的应用程序,如果你实际上没有找到另一个进程来杀死。
您的else
情况应该看起来像这样的伪代码:
dialogResult = MessageBox(...);
if (dialogResult == OK)
{
foreach (var p in ...)
{
// Todo: make sure you do not kill the current process!
p.Kill();
}
// now run the application
Application.Run(new Form1());
// now release the mutex
mut.Release();
}
else
{
mut.Close();
}
伪代码仍然需要一些异常处理,以确保在发生异常时正确释放互斥锁。
这解决你的问题了吗?而不是使用OpenExisting
,它没有文档保证在失败时返回null
,我使用Mutex
构造函数,它接受一个out bool
来确定互斥锁是否被创建或是否已经存在。启动应用程序并使用它执行任何操作(根据我所看到的部分猜测)都被移到了与创建互斥锁或关闭现有实例相关的所有操作之下。
步骤如下:
- 初始化
runApp
变量为true 尝试创建 - 检查
Mutex
是否已创建(不存在)- 如果
Mutex
没有创建,说明它已经存在- 询问用户是否想退出,等待互斥锁可用(表示强制退出现有应用程序实例完成)
- 如果他们不想退出,设置
runApp
为false
- 如果
检查
runApp
标志是否仍然为真如果为true,则运行应用程序。返回后(窗体退出),尝试connection
注意,这可能有一个错误,我不知道你是否打算阻止,因为你在应用程序。
释放互斥
Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); SqlConnection con123 = new SqlConnection(con123.Metoda()); string ProgramName = "Tray minimizer.exe"; bool mutCreated = false; Mutex mut = new Mutex(true, ProgramName, out mutCreated); bool runApp = true; if (!mutCreated) { DialogResult result = MessageBox.Show("Application is already working! Do you want to reopen it?", "Caution!", MessageBoxButtons.OKCancel); if (result == DialogResult.OK) { foreach (Process p in System.Diagnostics.Process.GetProcessesByName(ProgramName)) { try { p.Kill(); } catch { } } mut.WaitOne(); // Wait for ownership of the mutex to be released when the OS cleans up after the process being killed } else { runApp = false; } } if (runApp) { Application.Run(new Form1()); try { con123.Open(); con123.Close(); } catch { MessageBox.Show("Cant connect to server!!!", "Error!"); Application.Exit(); } mut.ReleaseMutex(); }
Mutex