Обеспечение только одного экземпляра приложения
Возможный дубликат:
Каков правильный способ создания одного экземпляра приложения?
У меня есть приложение 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;
Вышеуказанное находится в основной форме codebehind и вызывается из обработчика события загрузки.
Однако, как я могу гарантировать, что только один экземпляр приложения будет загружаться одновременно? В обработчике события загрузки основной формы я мог проверить, находится ли список процессов в системе (через GetProcessesByName (...)), но есть ли лучший метод?
Использование .NET 3.5.
Ответы
Ответ 1
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() в цикле, это не лучшая идея.
Ответ 2
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
}
}
Одно примечание об уникальном идентификаторе → это должно быть уникальным на машине, поэтому используйте что-то вроде имени вашей компании/имени приложения.
Edit:
http://sanity-free.org/143/csharp_dotnet_single_instance_application.html