以下哪个互斥表达式可以理想地防止 .Net 应用程序的多个实例,有什么区别?

发布于 2024-12-01 08:17:58 字数 1071 浏览 0 评论 0原文

通常我会到处看到这两段代码。两者都适用于我的情况,但我应该坚持哪一个呢?

案例 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;
}
  1. 两者之间防止多重实例的理想方法是什么?

  2. 有什么区别?

  3. 此外,我看到这样的代码:

    //如果不返回{
    互斥体.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;
}
  1. Which is the ideal way between the two to prevent multiple instances?

  2. What is the difference?

  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心房的律动 2024-12-08 08:17:58

在第一种情况下,您要求操作系统创建互斥锁,并在创建该互斥锁后向您授予其所有权 - 这是通过第一个参数 initiallyOwned 完成的。 isNew 参数告诉您它是否是一个新的互斥体。如果它是新的,那么您一定拥有它的所有权,因为这是您通过 initiallyOwned 参数所要求的。由于它是新的,并且您拥有它,因此您知道应用程序没有其他实例正在运行,因为如果有的话,它们就已经创建了互斥体并且拥有它。

第二种情况基本上是相同的事情,但以稍微不同的方式完成。它不是在创建时请求所有权,而是在 WaitOne 调用时请求所有权。 WaitOne 正在请求所有权,并等待 0 毫秒。如果您获得所有权,那么您就知道您的应用程序没有其他实例正在运行,原因与情况 1 相同

。据我所知,至于使用哪个实例并不重要。第一个似乎更直观,至少对我来说。

添加新问题#3的答案

当应用程序完成时,它应该释放互斥体,因为它拥有它。当您的应用程序退出时,.NET 可能会为您释放它,但这样做是一个很好的做法。 GC.CollectGC.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. The isNew 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 the initiallyOwned 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 and GC.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.

浪推晚风 2024-12-08 08:17:58

为了理解这些语句中发生的情况,我们必须了解互斥体是什么以及它们如何工作。我不会详细介绍,但我会向您推荐这本参考书。阅读前几章,直到阅读有关互斥体的部分。

第一个代码片段中的互斥体声明使用 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 for X seconds if it is locked by another thread. If the method doesn't get a signal response in X seconds, it returns false and, in the case of your sample code, enters the if 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文