应用程序的两种单例控制详解

应用程序的两种单例控制:1 关闭上一个进程,开启新的进程;2 保持上一个进程,阻止当前新开的进程

上述第一种:采用EventWaitHandle 实现了保持单例应用的功能,并且通过 EventWaitHandleSecurity 类型设置了信号量的访问权限,保证了多个进程之间的安全性

/// <summary>
    /// EventWaitHandle 实现了保持单例应用的功能,并且通过 EventWaitHandleSecurity 类型设置了信号量的访问权限,保证了多个进程之间的安全性
    /// </summary>
    class Program
    {
        private static void Main(string[] args)
        {
            _currentProcessId = Process.GetCurrentProcess().Id;
            SingletonApplication("Service");
            ProcessWait();
        }

        /// <summary>
        /// 保持单例应用
        /// </summary>
        /// <param name="appName"></param>
        private static void SingletonApplication(string appName)
        {
            string name = $"{Identification}" + appName;
            try
            {
                var security = SetEventWaitHandleSecurity();
                // name 以及createdNew 是关键,其中initialState 初始为false,WaitOne将等待到信号量set通过
                _singleWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, name, out bool createdNew, security);
                if (createdNew) return;
                DisposeOldSemaphore(name);
                _singleWaitHandle = CreateNewSemaphore(name, false, security);
                _singleWaitHandle.Reset();
            }
            catch (Exception arg)
            {
                Console.WriteLine($"保持单例出现异常:{arg}");
            }
        }

        /// <summary>
        /// 保证了多个进程之间的安全性
        /// </summary>
        /// <returns></returns>
        private static EventWaitHandleSecurity SetEventWaitHandleSecurity()
        {
            EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), EventWaitHandleRights.FullControl, AccessControlType.Allow);
            EventWaitHandleSecurity eventWaitHandleSecurity = new EventWaitHandleSecurity();
            eventWaitHandleSecurity.AddAccessRule(rule);
            return eventWaitHandleSecurity;
        }

        /// <summary>
        /// 释放旧的信号
        /// </summary>
        /// <param name="name"></param>
        private static void DisposeOldSemaphore(string name)
        {
            Console.WriteLine($"{_currentProcessId}:已经有一个进程在运行了,开始让上一个应用的信号量通过,然后等到上一个应用所持有的信号量退出之后,启动自己的信号量");
            _singleWaitHandle.Set();
            _singleWaitHandle.Dispose();
            while (EventWaitHandle.TryOpenExisting(name, out var handle))
                handle?.Dispose();
        }

        /// <summary>
        /// 创建新的信号量
        /// </summary>
        /// <param name="name"></param>
        /// <param name="createdNew"></param>
        /// <param name="security"></param>
        /// <returns></returns>
        private static EventWaitHandle CreateNewSemaphore(string name, bool createdNew, EventWaitHandleSecurity security)
        {
            Console.WriteLine($"{_currentProcessId}:开始创建属于自己的信号量"); 
            return new EventWaitHandle(initialState: false, EventResetMode.ManualReset, name, out createdNew, security);
        }

        /// <summary>
        /// 进程等待
        /// </summary>
        private static void ProcessWait()
        {
            Console.WriteLine($"{_currentProcessId}:信号量开始堵塞主线程");
            _singleWaitHandle.WaitOne();
            Console.WriteLine($"{_currentProcessId}:信号量收到通过信号,并开始Dispose信号量");
            _singleWaitHandle.Dispose();
            Console.WriteLine($"{_currentProcessId}:进程退出");
        }

        private const string Identification = "SingletonApp";
        private static EventWaitHandle _singleWaitHandle;
        private static int _currentProcessId;
    }

上述第二种:比较简单采用Mutex

    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App 
    {
        private static System.Threading.Mutex mutex;

        protected override void OnStartup(StartupEventArgs e)
        {
            //程序启动判断是否重复启动
            mutex = new System.Threading.Mutex(true, Assembly.GetExecutingAssembly().GetName().Name);
            if (!mutex.WaitOne(0, false))
            {
                System.Environment.Exit(0);
                return;
            }
            base.OnStartup(e);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值