首页 > 代码库 > 同一个应用程序只开启一个的方法

同一个应用程序只开启一个的方法

关键点——密封类Mutex

MSDN中Mutex类中是这样解释的:一个同步基元,也可用于进程间同步。其实个人感觉更容易理解的解释是:

互斥锁(Mutex)

互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它。

互斥锁可适用于一个共享资源每次只能被一个线程访问的情况。

如果要获取一个互斥锁。应调用互斥锁上的WaitOne()方法,该方法继承于Thread.WaitHandle类。

它处于等到状态直至所调用互斥锁可以被获取,因此该方法将组织住主调线程直到指定的互斥锁可用,如果不需要拥有互斥锁,用ReleaseMutex方法释放,从而使互斥锁可以被另外一个线程所获取。

这是我改自MSDN上的方法(其实也没改多少):

技术分享
 1 using System; 2 using System.Threading; 3  4 class Test 5 { 6     // Create a new Mutex. The creating thread does not own the 7     // Mutex. 8     private static Mutex mut = new Mutex(); 9     static void Main()10     {11         // Create the threads that will use the protected resource.12         for(int i = 0; i < 5; i++)13         {14             Thread myThread = new Thread(new ThreadStart(MyThreadProc));15             myThread.Name = String.Format("Thread{0}", i + 1);16             myThread.Start();17         }18 19         // The main thread exits, but the application continues to20         // run until all foreground threads have exited.21     }22 23     private static void MyThreadProc()24     {25           UseResource();26     }27 28     // This method represents a resource that must be synchronized29     // so that only one thread at a time can enter.30     private static void UseResource()31     {32         // Wait until it is safe to enter.33         mut.WaitOne();34 35         Console.WriteLine("{0} has entered the protected area", 36             Thread.CurrentThread.Name);37 38         // Place code to access non-reentrant resources here.39 40         // Simulate some work.41         Thread.Sleep(500);42 43         Console.WriteLine("{0} is leaving the protected area\r\n", 44             Thread.CurrentThread.Name);45          46         // Release the Mutex.47         mut.ReleaseMutex();48     }49 }
View Code

其实说白了就是:这个坑儿(Mutex mutex)谁蹲下,别个就只能等(mutex.WaitOne();),只有等蹲坑那个人爽完了(mutex.ReleaseMutex();),等待的那个人才能去蹲,然后再让另外的人去等待....

只开启一个应用程序实现

在程序的Program.cs里面,先添加如下代码:

先定义一个互斥锁: Mutex mutexCurrentApp. 

    bool flag = false;      mutexCurrentApp = new Mutex(true, Application.ProductName, out flag);  个参数:true--给调用线程赋予互斥体的初始所属权        //第一个参数:互斥体的名称        //第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true      if (!flag)      {          Process instance = GetExistProcesses();          if (instance != null)          {              SetForeground(instance);              return;           }       }  
GetExistProcesses()和 SetForeground(Process instance)的实现如下,这两个方法的作用就是:如果互斥体发现已经存在同名的互斥,就找到当前同名的进程,然后把这个进行的主窗体显示到屏幕的最前端。

技术分享
        private static Process GetExistProcess()        {            Process currentProcess = Process.GetCurrentProcess();            foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))            {                if (process.Id != currentProcess.Id && IsTheSameMainModule(currentProcess, process))                {                    return process;                }            }            return null;        }        private static bool IsTheSameMainModule(Process currentProcess, Process process)        {            try            {                return string.Equals(currentProcess.MainModule.ModuleName, process.MainModule.ModuleName);            }            catch (Win32Exception)            {            }            return true;        }        private static void SetForegroundWindow(Process instance)        {            IntPtr mainFormHandle = instance.MainWindowHandle;            if (mainFormHandle != IntPtr.Zero)            {                HandleRef mainFormhr = new HandleRef(instance, mainFormHandle);                ShowWindowAsync(mainFormhr, 1);                SetForegroundWindow(mainFormhr);            }        }        [DllImport("user32.dll", ExactSpelling = true)]        public extern static bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]        public extern static bool SetForegroundWindow(HandleRef hWnd);        
View Code

 

同一个应用程序只开启一个的方法