WPF Single Instance Best Practices

前端 未结 11 1513
名媛妹妹
名媛妹妹 2020-12-07 08:19

This is the code I implemented so far to create a single instance WPF application:

#region Using Directives
using System;
using System.Globalization;
using S         


        
11条回答
  •  囚心锁ツ
    2020-12-07 09:26

    I wanted to have a bit better user experience - if another instance is already running let's activate it rather than showing an error about the second instance. Here is my implementation.

    I use named Mutex for making sure that only one instance is running and named EventWaitHandle to pass notification from one instance to another.

    App.xaml.cs:

    /// Interaction logic for App.xaml
    public partial class App
    {
        #region Constants and Fields
    
        /// The event mutex name.
        private const string UniqueEventName = "{GUID}";
    
        /// The unique mutex name.
        private const string UniqueMutexName = "{GUID}";
    
        /// The event wait handle.
        private EventWaitHandle eventWaitHandle;
    
        /// The mutex.
        private Mutex mutex;
    
        #endregion
    
        #region Methods
    
        /// The app on startup.
        /// The sender.
        /// The e.
        private void AppOnStartup(object sender, StartupEventArgs e)
        {
            bool isOwned;
            this.mutex = new Mutex(true, UniqueMutexName, out isOwned);
            this.eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName);
    
            // So, R# would not give a warning that this variable is not used.
            GC.KeepAlive(this.mutex);
    
            if (isOwned)
            {
                // Spawn a thread which will be waiting for our event
                var thread = new Thread(
                    () =>
                    {
                        while (this.eventWaitHandle.WaitOne())
                        {
                            Current.Dispatcher.BeginInvoke(
                                (Action)(() => ((MainWindow)Current.MainWindow).BringToForeground()));
                        }
                    });
    
                // It is important mark it as background otherwise it will prevent app from exiting.
                thread.IsBackground = true;
    
                thread.Start();
                return;
            }
    
            // Notify other instance so it could bring itself to foreground.
            this.eventWaitHandle.Set();
    
            // Terminate this instance.
            this.Shutdown();
        }
    
        #endregion
    }
    

    And BringToForeground in MainWindow.cs:

        /// Brings main window to foreground.
        public void BringToForeground()
        {
            if (this.WindowState == WindowState.Minimized || this.Visibility == Visibility.Hidden)
            {
                this.Show();
                this.WindowState = WindowState.Normal;
            }
    
            // According to some sources these steps gurantee that an app will be brought to foreground.
            this.Activate();
            this.Topmost = true;
            this.Topmost = false;
            this.Focus();
        }
    

    And add Startup="AppOnStartup" (thanks vhanla!):

    
        
        
    
    

    Works for me :)

提交回复
热议问题