Amazon.com Widgets All posts tagged 'Mutex'

WilliaBlog.Net

I dream in code

About the author

Robert Williams is an internet application developer for the Salem Web Network.
E-mail me Send mail
Code Project Associate Logo
Go Daddy Deal of the Week: 30% off your order at GoDaddy.com! Offer expires 11/6/12

Recent comments

Archive

Authors

Tags

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.


Checking for a Running Instance

Sometimes you may not want a user to launch multiple instances of your program, or you may have a processor or I/O intensive scheduled task that runs every few minutes and you want to make sure that if it is started again before the last instance has finished it simply exits immediately. One way to check to see if your program is already running is to look at the list of running processes:

 

namespace RunningInstance

{

    using System;

    using System.Diagnostics;

    using System.Reflection;

 

    class Program

    {

        static void Main(string[] args)

        {

            if (RunningInstance())

            {

                Console.WriteLine("Another instance of this process was already running, exiting...");

                return;

            }

 

            // ...

        }

 

        static bool RunningInstance()

        {

            Process current = Process.GetCurrentProcess();

            Process[] processes = Process.GetProcessesByName(current.ProcessName);

 

            // Loop through the running processes in with the same name

            foreach (Process p in processes)

            {

                // Ignore the current process

                if (p.Id != current.Id)

                {

                    // Make sure that the process is running from the exe file.

                    if (Assembly.GetExecutingAssembly().Location.Replace("/", @"\") == current.MainModule.FileName)

                    {

                        return true;

                    }

                }

            }

 

            return false;

        }

    }

}

 

However, suppose you have a multi function console application that accepts a dozen different command line arguments to perform different jobs, all of which run as separate scheduled tasks at overlapping intervals. If this is the case, then checking the list of running processes may well find your executable already running, but have no idea which command line argument was used to start it. I tried adding:

 

Console.WriteLine("Instance started with args: '{0}'", p.StartInfo.Arguments);

above the "return true" statement in RunningInstance() but it will not print the command line args used to start it. Lets suppose we add 2 classes to our project. Task1 and Task2. For the sake of simplicity, they both look something like this:

namespace RunningInstance

{

    using System;

    using System.Threading;

 

    public class Task1

    { 

        public void Start()

        {

            Console.WriteLine("Starting Task 1");

        }

    }

}

 

Task 2 is exactly the same, except it prints "Starting Task 2". If we keep our RunningInstance check in place Main() now looks like this:

 

        static void Main(string[] args)

        {

            if (RunningInstance())

            {

                Console.WriteLine("An instance of this application is already running. Exiting.");

                Console.ReadLine();

                return;

            }

 

            if(args.Length < 1)

            {

                Console.WriteLine("Unrecognized Command.");

                return;

            }

 

            switch (args[0])

            {

                case "-task1":

                    var t1 = new Task1();

                    t1.Start();

                    break;

                case "-task2":

                    var t2 = new Task2();

                    t2.Start();

                    break;

                default:

                    Console.WriteLine("Unrecognized Command.");

                    break;

            }

        }

Task 2 will not run, if task 1 is still running, and vice versa. However, suppose the two tasks are completely unrelated. The first is only a minor chore, that simply counts the number of items marked as "queued" in a database table and sends out an email if the number is too high, while task 2 is much lengthier process that FTPs files. We may need both of these tasks to run as scheduled, but not want multiple instances of either task to run at the same time. How can we achive this? We use a Mutex. Mutex is an abbreviation of "Mutual exclusion" and is traditionally used in multi threaded applications to avoid the simultaneous use of a common resource, such as a global variable. After adding a mutex to each task, our final code looks like this:


        static void Main(string[] args)

        { 

            if(args.Length < 1)

            {

                Console.WriteLine("Unrecognized Command.");

                return;

            }

 

            switch (args[0])

            {

                case "-task1":

                    var t1 = new Task1();

                    t1.Start();

                    break;

                case "-task2":

                    var t2 = new Task2();

                    t2.Start();

                    break;

                default:

                    Console.WriteLine("Unrecognized Command.");

                    break;

            }

        }

 

 

namespace RunningInstance

{

    using System;

    using System.Threading;

 

    public class Task1

    {

        /// <summary>Gets the mutex that prevents multiple instances of this code running at once.</summary>

        private static Mutex mutex1;

 

        public void Start()

        {

            bool createdNew;

            mutex1 = new Mutex(true, "RunningInstance.Task1", out createdNew);

            if (!createdNew)

            {

                // Instance already running; exit.

                Console.WriteLine("Exiting: Instance already running");

                return;

            }

 

            Console.WriteLine("Starting Task 1");

        }

    }

}

 

 

namespace RunningInstance

{

    using System;

    using System.Threading;

 

    public class Task2

    {

        /// <summary>Gets the mutex that prevents multiple instances of this code running at once.</summary>

        private static Mutex mutex1;

 

        public void Start()

        {

            bool createdNew;

            mutex1 = new Mutex(true, "RunningInstance.Task2", out createdNew);

            if (!createdNew)

            {

                // Instance already running; exit.

                Console.WriteLine("Exiting: Instance already running");

                return;

            }

            Console.WriteLine("Starting Task 2");

        }

    }

}

 

Each Task has its own Mutex, uniquely named. If the mutex already exists, then that code must already be running, so exit, otherwise, run. Couldn't be simpler. By using this particular overload of the constructor, we don't even need to worry about releasing the mutex at the end of the program.

Categories: C# | CodeProject
Posted by Williarob on Monday, October 04, 2010 5:57 AM
Permalink | Comments (0) | Post RSSRSS comment feed