Force Single Instance with Mutex handling restart application

给你一囗甜甜゛ 提交于 2020-07-30 12:00:12

问题


I have a problem when i want use mutex to force single instance of my program.

I a winform App with a WebBrowser Control. I need to autorestart if certain conditions are met.

My Problem is that if i restart the application the mutex want let me open a new instance (this doesn't always happen) maybe cause browser has some async method like navigate.

But i release the Mutex in Exit Application Event.

This is my Code:

    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();
    }

回答1:


Single instance apps are well supported by the framework. It supports goodies such as disabling it on-the-fly, what you need here, and getting a notification when another instance is started. You'll want to use that to give your first instance the focus. Rewrite your Program.cs code like this:

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;
    }
}



回答2:


Try using try..finally for managing the Mutex.

I usually use this approach. Worked well in combination with 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());
    }



回答3:


I'm not sure what exactly goes wrong in your case but some issues might be:

  • You should probably use try finally to close the mutex to maximize changes of proper cleanup
  • In case cleanup failed previous time then Mutex.WaitOne will throw an AbandonedMutexException instead of return true. In this case your code will exit with an error box while you can just continue.
  • You are giving the Mutex 5 seconds to get aquired. If your shutdown will take over 5 seconds then the next startup will fail. A better option might be to release mutex right before initiating shutdown. (Provided of course that the Mutex is there only for user convenience).

example

the following example will require that you use Program.Restart to restart the application. Else the time window can still be the problem.

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();
        }
    }
}



回答4:


I do:

    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();
        }


来源:https://stackoverflow.com/questions/9456182/force-single-instance-with-mutex-handling-restart-application

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!