zoukankan      html  css  js  c++  java
  • 使用Mutex实现会话状态下单实例运行和系统范围内单实例运行

    最近在做一个作业调度的ConsoleApp,作业调度部分本文暂不讨论(以后会写),本文只讨论如何保证单实例运行。

    ConsoleApp运行要求

    1、系统启动时启动该应用;

    2、每会话状态下单实例运行;

        开启一个远程桌面链接时,ConsoleApp只允许被启动一个实例。

    3、系统范围内只能有一个实例运行;

        开启多个远程桌面链接时,ConsoleApp只允许被启动一个实例。

    Mutex

    Mutex(互斥体):一个同步基元,也可用于进程间同步。

    可见MSND:http://msdn.microsoft.com/zh-cn/library/system.threading.mutex.aspx

    在官方文档的介绍中,有这样一段话

    在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex。如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。在终端服务器会话中,只是名称前缀不同的两个 mutex 是独立的 mutex,这两个 mutex 对于终端服务器会话中的所有进程均为可见。即:前缀名称“Global\”和“Local\”说明 mutex 名称相对于终端服务器会话(而并非相对于进程)的范围。

    很可惜没有找到C#示例,这段话可以理解为:

    mutexName= "Local\\" +"AppName";

    只对创建它的会话有效,也就是说新开启一个远程链接时会再次启动 ConsoleApp实例。

    mutexName= "Global\\" +"AppName";

    对所有会话有效,开启多个远程链接时,只有第一个远程链接会成功启动 ConsoleApp实例。

    每会话状态下单实例运行

       private static void LocalMutex()
            {
                
    // 是否第一次创建mutex
                bool newMutexCreated = false;
                
    string mutexName = "Local\\" + "tenghoo";
                Mutex mutex 
    = null;
                
    try
                {
                    mutex 
    = new Mutex(false, mutexName, out newMutexCreated);
                }
                
    catch (Exception ex)
                {
                    Console.Write(ex.Message);
                    System.Threading.Thread.Sleep(
    3000);
                    Environment.Exit(
    1);
                }

                
    // 第一次创建mutex
                if (newMutexCreated)
                {
                    Console.WriteLine(
    "程序已启动");
                   
    //todo:此处为要执行的任务
                }
                
    else
                {
                    Console.Write(
    "另一个窗口已在运行,3秒以后自动关闭。。");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "1");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "2");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "3");
                    Environment.Exit(
    1);//退出程序
                }
            }

    系统范围内单实例运行

       private static void GlobalMutex()
            {
                
    // 是否第一次创建mutex
                bool newMutexCreated = false;
                
    string mutexName = "Global\\" + "tenghoo";
                Mutex mutex 
    = null;
                
    try
                {
                    mutex 
    = new Mutex(false, mutexName, out newMutexCreated);
                }
                
    catch (Exception ex)
                {
                    Console.Write(ex.Message);
                    System.Threading.Thread.Sleep(
    3000);
                    Environment.Exit(
    1);
                }

                
    // 第一次创建mutex
                if (newMutexCreated)
                {
                    Console.WriteLine(
    "程序已启动");
                   
    //todo:此处为要执行的任务
                }
                
    else
                {
                    Console.Write(
    "另一个窗口已在运行,3秒以后自动关闭。。");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "1");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "2");
                    System.Threading.Thread.Sleep(
    1000);
                    Console.Write(
    "3");
                    Environment.Exit(
    1);//退出程序
                }
            }



  • 相关阅读:
    类型构造器
    WIN32画图窗口
    WIN32创建进程CreateProcess
    WIN通过消息实现互斥同步CreateEvent和SetEvent
    WIN32生产消费经典同步但是以消耗时间为代价
    WIN32互斥体CreateMutex以及限制多开
    WIN32临界区线程锁EnterCriticalSection和LeaveCriticalSection
    GetThreadContext和SetThreadContext
    远程线程注入
    EnumProcessModules 使用 获取进程的路径
  • 原文地址:https://www.cnblogs.com/tenghoo/p/mutex.html
Copyright © 2011-2022 走看看