Ensuring only one application instance
Solution 1
GetProcessesByName is slow way of checking if another instance is running. The fastest and elegant method is using mutex:
[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
}
Please also bear in mind that the code you presented is not the best approach. As it was advised in one of comments calling DoEvents() in a loop is not the best idea.
Solution 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
}
}
One note about the some-unique-id -> this should be unique on the machine, so use something like your company name / application name.
Edit:
http://sanity-free.org/143/csharp_dotnet_single_instance_application.html
Related videos on Youtube
GurdeepS
Updated on July 09, 2022Comments
-
GurdeepS almost 2 years
Possible Duplicate:
What is the correct way to create a single instance application?I have a Winforms app, which launches a splash screen via the following code:
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;
The above is in the main form's codebehind and called from the load event handler.
However, how can I ensure that only one instance of the application will load at a time? In the load event handler of the main form, I could check if the process list is on the system (via GetProcessesByName(...)), but is there a better method?
Using .NET 3.5.
-
SLaks almost 13 yearsYou should call
Application.Run(splashForm)
instead of aDoEvents()
loop.
-
-
monstr about 10 yearsGC.KeepAlive(mutex); - doesn't work for me by some reasons. I was forsed to use private static mutex;
-
Alex B. over 9 yearsI may be wrong, but shouldn't 'GC.KeepAlive(mutex);' line be before 'Application.Run(new Form1());'? 'Application.Run()' method starts the program's message loop and does not return until 'Form1' is closed.
-
michalczerwinski about 9 years@AlexB.: no, this is on purpose. The goal is to prevent mutex from being released, which can occured when a new form is opened and Form1 is closed. Before Form1 is closed there is no risk of mutex being released
-
bh_earth0 about 8 yearsin if block, putting "application.exit()" instead of "return ", works form me, but i put the mutex check in the form1's form_load .
-
qakmak about 8 yearsWhy some people recommend use
mutex.ReleaseMutex()
, what's the difference betweenGC.KeepAlive(mutex)
?