使用Mutex处理重启应用程序强制单个实例

时间:2012-02-26 19:07:10

标签: .net mutex restart

当我想使用互斥锁强制我的程序的单个实例时,我遇到了问题。

我是一个带有WebBrowser控件的winform应用程序。如果满足某些条件,我需要自动重启。

我的问题是,如果我重新启动应用程序,互斥锁希望让我打开一个新实例(这并不总是发生)可能导致浏览器有一些异步方法,如导航。

但是我在退出申请活动中发布了Mutex。

这是我的代码:

    static Mutex _mutex = new Mutex (false, "myprogramkey");

    [STAThread]
    private static void Main()
    { 
         Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
      if(_mutex.WaitOne(TimeSpan.FromSeconds(5), true))
      { 
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new RevolutionForm()); 
      }

     else
      {
          MessageBox.Show("Error!");
      }
    }
        static void Application_ApplicationExit(object sender, EventArgs e)
    {
        _mutex.ReleaseMutex();
    }

4 个答案:

答案 0 :(得分:3)

框架很好地支持单实例应用程序。它支持好处,例如在运行中禁用它,在这里需要什么,以及在另一个实例启动时获取通知。您将要使用它来为您的第一个实例提供焦点。重写你的Program.cs代码:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;   // NOTE: add reference to Microsoft.VisualBasic

namespace WindowsFormsApplication1 {
    class Program : WindowsFormsApplicationBase {
        public Program() {
            EnableVisualStyles = true;
            MainForm = new Form1();
            IsSingleInstance = true;
        }
        public static void Main(string[] args) {
            Instance = new Program();
            Instance.Run(args);
        }
        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) {
            // Nicety, focus the single instance.
            Instance.MainForm.Activate();
        }
        public static void Restart() {
            // What you asked for.  Use Program.Restart() in your code
            Instance.IsSingleInstance = false;
            Application.Restart();
        }
        private static Program Instance;
    }
}

答案 1 :(得分:0)

尝试使用try..finally来管理互斥锁。

我通常使用这种方法。与Application.Restart()结合使用效果很好。

    private const string ApplicationMutexName = "<myprogramkey>";

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    public static void Main()
    {
        RunApplicationPreservingSingleInstance();
    }

    private static void RunApplicationPreservingSingleInstance()
    {
        Mutex mutex = AcquireMutex();
        if (mutex == null)
        {
            return;
        }

        try
        {
            RunApplication();
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }

    private static Mutex AcquireMutex()
    {
        Mutex appGlobalMutex = new Mutex(false, ApplicationMutexName);
        if (!appGlobalMutex.WaitOne(3000))
        {
            return null;
        }
        return appGlobalMutex;
    }

    private static void RunApplication()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }

答案 2 :(得分:0)

我不确定你的情况究竟出了什么问题,但有些问题可能是:

  • 您应该使用try finally关闭互斥锁以最大限度地更改正确的清理
  • 如果以前清理失败,Mutex.WaitOne会抛出AbandonedMutexException而不是返回true。在这种情况下,您可以继续使用错误框退出代码。
  • 你给Mutex 5秒钟获得了获得。如果关机将花费5秒钟,那么下次启动将失败。更好的选择可能是在启动关闭之前释放互斥锁。 (当然,Mutex仅供用户使用)。

示例

以下示例将要求您使用Program.Restart重新启动应用程序。否则时间窗口仍然是问题。

static class Program
{
    private static Mutex _mutex;

    [STAThread]
    static void Main()
    {
        _mutex = new Mutex(false, "myprogramkey");
        try
        {
            try
            {
                if (!_mutex.WaitOne(1))
                {
                    _mutex.Dispose();
                    _mutex = null;
                    MessageBox.Show("Error!");
                    return;
                }
            }
            catch (AbandonedMutexException) { /* Mutex wasn't property released last time.*/ }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        finally
        {
            if (_mutex != null)
            {
                _mutex.ReleaseMutex();
                _mutex.Dispose();
            }
        }
    }

    public static void Restart()
    {
        if (_mutex != null)
        {
            _mutex.ReleaseMutex();
            _mutex.Dispose();
            _mutex = null;
            Application.Restart();
        }
    }
}

答案 3 :(得分:0)

我这样做:

    bool onlyInstance = false;
        mutex = new System.Threading.Mutex(true, "qFluid", out onlyInstance);
        int cntrSec = 0;
        //per far funzionare restart ,aspetto per 3 sec per vedere se va via servizio 
        while (!onlyInstance & cntrSec < 3)
        {
            System.Threading.Thread.Sleep(1000);
            cntrSec += 1;
        }

        if (!onlyInstance)
        {
            Xceed.Wpf.Toolkit.MessageBox.Show("The application is already arunning");
            App.Current.Shutdown();
        }