【问题标题】:Run single instance of an application using Mutex使用 Mutex 运行应用程序的单个实例
【发布时间】:2010-10-23 14:47:30
【问题描述】:

为了只允许应用程序的单个实例运行,我正在使用互斥锁。代码如下。这是正确的方法吗?代码有缺陷吗?

当用户第二次尝试打开应用程序时如何显示已经运行的应用程序。目前(在下面的代码中),我只是显示另一个实例已经在运行的消息。

    static void Main(string[] args)
    {
        Mutex _mut = null;

        try
        {
            _mut = Mutex.OpenExisting(AppDomain.CurrentDomain.FriendlyName);
        }
        catch
        {
             //handler to be written
        }

        if (_mut == null)
        {
            _mut = new Mutex(false, AppDomain.CurrentDomain.FriendlyName);
        }
        else
        {
            _mut.Close();
            MessageBox.Show("Instance already running");

        }            
    }

【问题讨论】:

标签: c# mutex


【解决方案1】:

我做过一次,希望对你有帮助:

bool createdNew;

Mutex m = new Mutex(true, "myApp", out createdNew);

if (!createdNew)
{
    // myApp is already running...
    MessageBox.Show("myApp is already running!", "Multiple Instances");
    return;
}

【讨论】:

  • 此代码不安全或不正确:stackoverflow.com/questions/229565/…
  • 我希望这是安全和正确的。它非常简单,无需任何思考就可以轻松编写,哈哈。不过,为你们俩 +1。
  • @SamSaffron - 您是说仅在多个用户可能请求互斥锁的情况下它是不安全和不正确的,还是在仅由单个用户请求互斥锁的情况下它是不安全和不正确的也一样?
  • 我不同意 Sam 的评论(以及反对票)。该代码不使用互斥同步。相反,互斥锁仅用于确定是否已由另一个进程创建,并且在进程终止(包括异常终止)时将被销毁。在看到解释为什么它不正确之前,我会认为它是安全和正确的。问题可能是恶意应用程序获取了互斥锁,并且进程在不同的会话中运行了两次。前者是破坏,后者被问题所涵盖(“用户试图第二次打开应用程序”)。
  • 这应该放在我的 C# 应用程序的哪个函数中?
【解决方案2】:
static void Main() 
{
  using(Mutex mutex = new Mutex(false, @"Global\" + appGuid))
  {
    if(!mutex.WaitOne(0, false))
    {
       MessageBox.Show("Instance already running");
       return;
    }

    GC.Collect();                
    Application.Run(new Form1());
  }
}

来源:http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx

【讨论】:

  • 此代码不安全或不正确...stackoverflow.com/questions/229565/…
  • 'Global' 使其对机器来说是全局的,而不是对正在运行的用户。因此,在服务器环境或终端服务中,一次只有一个用户可以运行它。我认为大多数用户期望单个实例对他们来说意味着单个实例。
【解决方案3】:

我用这个:

    private static Mutex _mutex;

    private static bool IsSingleInstance()
    {
        _mutex = new Mutex(false, _mutexName);

        // keep the mutex reference alive until the normal 
        //termination of the program
        GC.KeepAlive(_mutex);

        try
        {
            return _mutex.WaitOne(0, false);
        }
        catch (AbandonedMutexException)
        {
            // if one thread acquires a Mutex object 
            //that another thread has abandoned 
            //by exiting without releasing it

            _mutex.ReleaseMutex();
            return _mutex.WaitOne(0, false);
        }
    }


    public Form1()
    {
        if (!isSingleInstance())
        {
            MessageBox.Show("Instance already running");
            this.Close();
            return;
        }

        //program body here
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (_mutex != null)
        {
            _mutex.ReleaseMutex();
        }
    }    

【讨论】:

    【解决方案4】:

    看看this question

    本文有一个链接:the misunderstood mutex,其中解释了互斥锁的用法。

    【讨论】:

      【解决方案5】:

      查看this page上显示的代码示例

      简而言之,您使用重载 Mutex ctor(bool, string, out bool),它通过 out 参数告诉您,您是否拥有 Named Mutex 的所有权。如果您是第一个实例,则在调用 ctor 后,此输出参数将包含 true - 在这种情况下,您将照常进行。如果此参数为 false,则表示另一个实例已经获得所有权/正在运行,在这种情况下,您会显示错误消息“另一个实例已在运行”。然后优雅地退出。

      【讨论】:

        【解决方案6】:

        使用具有超时和安全设置的应用。我使用了我的自定义类:

        private class SingleAppMutexControl : IDisposable
            {
                private readonly Mutex _mutex;
                private readonly bool _hasHandle;
        
                public SingleAppMutexControl(string appGuid, int waitmillisecondsTimeout = 5000)
                {
                    bool createdNew;
                    var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                        MutexRights.FullControl, AccessControlType.Allow);
                    var securitySettings = new MutexSecurity();
                    securitySettings.AddAccessRule(allowEveryoneRule);
                    _mutex = new Mutex(false, "Global\\" + appGuid, out createdNew, securitySettings);
                    _hasHandle = false;
                    try
                    {
                        _hasHandle = _mutex.WaitOne(waitmillisecondsTimeout, false);
                        if (_hasHandle == false)
                            throw new System.TimeoutException();
                    }
                    catch (AbandonedMutexException)
                    {
                        _hasHandle = true;
                    }
                }
        
                public void Dispose()
                {
                    if (_mutex != null)
                    {
                        if (_hasHandle)
                            _mutex.ReleaseMutex();
                        _mutex.Dispose();
                    }
                }
            }
        

        并使用它:

            private static void Main(string[] args)
            {
                try
                {
                    const string appguid = "{xxxxxxxx-xxxxxxxx}";
                    using (new SingleAppMutexControl(appguid))
                    {
        
                        Console.ReadLine();
                    }
                }
                catch (System.TimeoutException)
                {
                    Log.Warn("Application already runned");
                }
                catch (Exception ex)
                {
                    Log.Fatal(ex, "Fatal Error on running");
                }
            }
        

        【讨论】:

          【解决方案7】:
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-04-10
          • 1970-01-01
          • 1970-01-01
          • 2021-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多