以下哪个互斥表达式可以理想地防止 .Net 应用程序的多个实例,有什么区别?
通常我会到处看到这两段代码。两者都适用于我的情况,但我应该坚持哪一个呢?
案例 1:
bool isNew = false;
Mutex mutex = new Mutex(true, "MyApp_Mutex", out isNew);
if (!isNew)
{
MessageBox.Show("already running.", "Multiple Instances Not Allowed",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
案例 2:
Mutex mutex = new Mutex(false, "MyApp_Mutex"))
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("already running.", "Multiple Instances Not Allowed",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
两者之间防止多重实例的理想方法是什么?
有什么区别?
此外,我看到这样的代码:
//如果不返回{ 互斥体.ReleaseMutex(); GC.Collect(); //应用程序.Run(); GC.KeepAlive(互斥体);
在第二种方法下,但从未使用第一种方法。为什么会这样呢?还是我弄错了?
基本上,这取决于对所使用的参数和方法的正确理解。如果有人能简要详细说明它,我将不胜感激,在阅读 msdn 文档时我理解不到一半。
Typically I see these two pieces of code all around. Both works in my case too, but which should I stick to?
Case 1:
bool isNew = false;
Mutex mutex = new Mutex(true, "MyApp_Mutex", out isNew);
if (!isNew)
{
MessageBox.Show("already running.", "Multiple Instances Not Allowed",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
Case 2:
Mutex mutex = new Mutex(false, "MyApp_Mutex"))
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("already running.", "Multiple Instances Not Allowed",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
Which is the ideal way between the two to prevent multiple instances?
What is the difference?
Moreover I see codes like these:
//if not return{ mutex.ReleaseMutex(); GC.Collect(); //application.Run(); GC.KeepAlive(mutex);
under the second method but never with the first. Why is that so? Or did I get that wrong?
Basically it lies with the proper understanding of the parameters and methods used. I would appreciate if someone can briefly detail it, I understand not half when reading msdn documentation..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在第一种情况下,您要求操作系统创建互斥锁,并在创建该互斥锁后向您授予其所有权 - 这是通过第一个参数
initiallyOwned
完成的。isNew
参数告诉您它是否是一个新的互斥体。如果它是新的,那么您一定拥有它的所有权,因为这是您通过initiallyOwned
参数所要求的。由于它是新的,并且您拥有它,因此您知道应用程序没有其他实例正在运行,因为如果有的话,它们就已经创建了互斥体并且拥有它。第二种情况基本上是相同的事情,但以稍微不同的方式完成。它不是在创建时请求所有权,而是在
WaitOne
调用时请求所有权。WaitOne
正在请求所有权,并等待 0 毫秒。如果您获得所有权,那么您就知道您的应用程序没有其他实例正在运行,原因与情况 1 相同。据我所知,至于使用哪个实例并不重要。第一个似乎更直观,至少对我来说。
添加新问题#3的答案
当应用程序完成时,它应该释放互斥体,因为它拥有它。当您的应用程序退出时,.NET 可能会为您释放它,但这样做是一个很好的做法。
GC.Collect
和GC.KeepAlive
正在处理垃圾收集。我想不出在处理控制启动的互斥体时需要这些调用的任何场景。我将互斥体声明为静态,因此它将始终在范围内,并且在我的应用程序的生命周期内不会被垃圾收集器释放。In the first case, you're asking the OS to create the mutex and give you ownership of it if it's created - this is done through the first parameter,
initiallyOwned
. TheisNew
parameter tells you whether or not it was a new mutex. If it's new then you're guaranteed to have ownership of it since that's what you asked for with theinitiallyOwned
parameter. Since it's new, and you own it, you know there are no other instances of the application running, because if there were, they would have already created the mutex and they would own it.The second case is basically the same thing, but done in a slightly different way. It's not requesting ownership on the create, but on the
WaitOne
call.WaitOne
is requesting ownership, and waiting for 0 milliseconds. If you get ownership then you know no other instance of your app is running, for the same reasons as case 1.As for which to use, to my knowledge it doesn't matter. The first seems to be more intuitive, at least to me.
Adding answer to new question #3
When the app is complete it should release the mutex since it owns it. .NET will likely release it for you when your app exits, but it's good practice to do it.
GC.Collect
andGC.KeepAlive
are dealing with garbage collection. I can't think of any scenario why these calls would be needed when dealing with the mutexes controlling startup. I declare my mutex as static, so it will always be in scope and won't be freed by the garbage collector for the lifetime of my app.为了理解这些语句中发生的情况,我们必须了解互斥体是什么以及它们如何工作。我不会详细介绍,但我会向您推荐这本参考书。阅读前几章,直到阅读有关互斥体的部分。
第一个代码片段中的互斥体声明使用 isNew 布尔值来指定当前应用程序实例是第一个运行的,也是第一个创建互斥体的实例。这意味着应用程序的每个辅助执行都可以被告知它们对系统范围互斥体的句柄不是第一个创建和访问互斥体的句柄。
然后,以下
if
块检查关联任务是否是第一个向互斥体发出信号的任务,然后相应地处理状态。第二段代码完全不同。互斥锁可用于任务(任务 B)中,以等待另一个任务(任务 A)向互斥锁发出任何其他任务(任务 B)可以继续的信号。
WaitOne(secs, releaseConext)
方法表示,如果互斥体被另一个线程锁定,则等待X
秒发送信号响应 >。如果该方法在X
秒内未收到信号响应,则会返回false
,并且对于示例代码,会输入if
用于关闭应用程序的块。就我个人而言,我会使用第一段代码。我想它们的运行开销是相同的。然而,在选择使用哪个版本时,我认为第一种方法是一般实践中最好使用的方法。
In order to understand what is going on in these statements, one must understand what a mutex is and how they operate. I won't go into any great detail but I will point you to this reference book. Read the first few chapters until you get to the section about Mutexes.
The declaration of the Mutex in your first snippet of code uses the
isNew
bool to specify that the current application instance was the first to run, as well as the first instance to create the Mutex. This means each secondary execution of your application can be informed that their handle to the system-wide Mutex was not the first one to create and access the Mutex.The following
if
block then checks to see if the associated task was the first to signal the Mutex and then handles the state accordingly.The second snippet of code is completely different. A Mutex can be used in a task (task B) to wait for another task (task A) to signal the Mutex that any other task (task B) can continue.
The
WaitOne(secs, releaseConext)
method is saying, wait for the Mutex to send a Signal response forX
seconds if it is locked by another thread. If the method doesn't get a signal response inX
seconds, it returnsfalse
and, in the case of your sample code, enters theif
block which is used to close the application.Personally, I would use the first snippet of code. I would imagine that they both operate with the same amount of overhead. However, in choosing which version to use I would consider the first method to be the best one to use as a general matter of practice.