2011-06-26 50 views
17

可能重复:
What is the correct way to create a single instance application?确保只有一个应用程序实例

我有一个WinForms应用程序,它通过下面的代码启动一个闪屏:

Hide(); 
     bool done = false; 
     // Below is a closure which will work with outer variables. 
     ThreadPool.QueueUserWorkItem(x => 
            { 
             using (var splashForm = new SplashScreen()) 
             { 
              splashForm.Show(); 
              while (!done) 
               Application.DoEvents(); 
              splashForm.Close(); 
             } 
            }); 

     Thread.Sleep(3000); 
     done = true; 

的上面是主窗体的代码隐藏,并从加载事件处理程序调用。

但是,如何确保一次只加载一个应用程序实例?在主窗体的加载事件处理程序中,我可以检查进程列表是否在系统上(通过GetProcessesByName(...)),但有没有更好的方法?

使用.NET 3.5。

+1

你应该叫'Application.Run(splashForm)',而不是'的DoEvents()'循环。 – SLaks

回答

50

GetProcessesByName是检查另一个实例是否正在运行的缓慢方式。最快最优雅的方法是使用互斥锁:

[STAThread] 
    static void Main() 
    { 
     bool result; 
     var mutex = new System.Threading.Mutex(true, "UniqueAppId", out result); 

     if (!result) 
     { 
      MessageBox.Show("Another instance is already running."); 
      return; 
     } 

     Application.Run(new Form1()); 

     GC.KeepAlive(mutex);    // mutex shouldn't be released - important line 
    } 

请注意,您提供的代码不是最好的方法。正如其中一条评论中所建议的,在循环中调用DoEvents()并不是最好的主意。对一些器唯一ID

+0

GC.KeepAlive(mutex); - 由于某些原因,不适合我。我被禁止使用私人静态互斥体 ; – monstr

+0

我可能是错的,但不应该'GC.KeepAlive(mutex);'在'Application.Run(new Form1());'之前? 'Application.Run()'方法启动程序的消息循环,直到'Form1'关闭才会返回。 –

+0

@亚历克斯:不,这是故意的。目标是防止互斥体被释放,当一个新窗体被打开并且Form1被关闭时可能会发生互斥体。在Form1关闭之前,如果block中没有释放互斥量 – michalczerwinski

16
static class Program 
{ 
    // Mutex can be made static so that GC doesn't recycle 
    // same effect with GC.KeepAlive(mutex) at the end of main 
    static Mutex mutex = new Mutex(false, "some-unique-id"); 

    [STAThread] 
    static void Main() 
    { 
     // if you like to wait a few seconds in case that the instance is just 
     // shutting down 
     if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false)) 
     { 
      MessageBox.Show("Application already started!", "", MessageBoxButtons.OK); 
      return; 
     } 

     try 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 
     finally { mutex.ReleaseMutex(); } // I find this more explicit 
    } 
} 

一个说明 - >这应该是机上唯一的,因此使用像您的公司名称/应用程序名称。

编辑:

http://sanity-free.org/143/csharp_dotnet_single_instance_application.html

相关问题