2

I am not sure why the code below won't enforce a single instance application on my work machine (Win7) but it works fine on my personal machine (Win8) at home (e.g. only one instance of the application can be run at a time). As far as I know each kernel handle object with the same name can only be created once. But I can run multiple instances of the application on my work machine...

static void Main(string[] args)
{
    bool createNew;
    const string appName = "TestMyApplication";
    using (new Semaphore(0, 1, appName, out createNew))
    {
        if (createNew)
        {
            Console.WriteLine("One instance of MyApplication is created and running...");
        }
        else
        {
            Console.WriteLine("Only one instance of MyApplication can be running at a time... Auto shut down in 3 seconds...");
            Thread.Sleep(3000);
        }
    }
   Console.ReadKey();
}
dragonfly02
  • 3,403
  • 32
  • 55
  • 1
    Have you seen http://stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-application?rq=1? – John Saunders Apr 28 '15 at 15:12
  • That lasts for only 3000ms then its destroyed .. – Alex K. Apr 28 '15 at 15:13
  • Mutext is a better option here, if you want to execute only one program. (Mutex is a semaphotre with capacity equals to 1). See http://stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-application – Alex Sikilinda Apr 28 '15 at 15:14
  • @JohnSaunders, AlexSikilinda My question here is mainly why this won't work rather than which is better at creating single instance application. – dragonfly02 Apr 28 '15 at 15:20
  • 2
    @stt106 Put your `Console.ReadKey()` inside your semaphore's `using`. – TyCobb Apr 28 '15 at 15:21
  • @AlexK. Not sure what you mean. My intention was if another instance is running already, the second instance will auto shut in 3 seconds; this is just for testing anyway. – dragonfly02 Apr 28 '15 at 15:22
  • 1
    The semaphore needs to live as long as the first instance so the second can detect it, currently the semaphore is always destroyed when the using block completes so the second instance is free to create a new one – Alex K. Apr 28 '15 at 15:23
  • @TyCobb you just made me feel stupid... but thank you! – dragonfly02 Apr 28 '15 at 15:25
  • Ok the reason is, as Alex K and TyCobb mentioned, when the semaphore object disposes it will also dispose the underlying kernel object hence each instance is allowed to create a new one... – dragonfly02 Apr 28 '15 at 15:28

1 Answers1

4

Your Console.ReadKey() is outside of the semaphore's scope. Your lock is getting destroyed instantly before your next application runs so it appears that both are running.

Below is the change that can be made to keep your 1st instance alive and still lock the other with an actual shut down.

using (new Semaphore(0, 1, appName, out createNew))
{
    if (createNew)
    {
        Console.WriteLine("One instance of MyApplication is created and running...");
        Console.ReadKey();
    }
    else
    {
        Console.WriteLine("Only one instance of MyApplication can be running at a time... Auto shut down in 3 seconds...");
        Thread.Sleep(3000);
        return;
    }
}
TyCobb
  • 8,909
  • 1
  • 33
  • 53
  • 1
    Totally agree! This is why it's risky to dispose kernel mode constructs as it will also dispose underlying kernal handle which might be used by other threads or processes... – dragonfly02 Apr 28 '15 at 15:31