Problem

You need to synchronize tasks such that only one task runs in a certain critical section.

Solution

Use Window's mutexes, which are exposed to .NET with the System.Threading..::..Mutex class. Check MSDN for more information on how to use mutexes.

C#  Copy imageCopy
using System;
using System.Diagnostics;
using System.Threading;
using AGI.Parallel.Client;
using AGI.Parallel.Infrastructure;

namespace CodeSamples
{
    class Program
    {
        static void Main(string[] args)
        {
            using (IJobScheduler scheduler = new ClusterJobScheduler("localhost"))
            {
                scheduler.Connect();
                Job job = scheduler.CreateJob();

                for (int i = 0; i < 8; i++)
                {
                    job.AddTask(new SyncAccessToMachineResourceTask { TaskNumber = i + 1 });
                }

                job.Submit();
                job.WaitUntilDone();

                for (int i = 0; i < 8; ++i)
                {
                    Console.WriteLine(job.Tasks[i].GetProperty<string>("resource-start"));
                    Console.WriteLine(job.Tasks[i].GetProperty<string>("resource-stop"));
                    Console.WriteLine();
                }
            }

            /*
             * The output of the application should resemble:
             * Agent=AgentComputerName1 PID=12008 accessing resource at 2/28/2013 7:07:46 PM
             * Agent=AgentComputerName1 PID=12008 done accessing resource at 2/28/2013 7:07:51 PM
             *
             * Agent=AgentComputerName1 PID=11552 accessing resource at 2/28/2013 7:08:01 PM
             * Agent=AgentComputerName1 PID=11552 done accessing resource at 2/28/2013 7:08:06 PM
             *
             * Agent=AgentComputerName1 PID=9364 accessing resource at 2/28/2013 7:07:56 PM
             * Agent=AgentComputerName1 PID=9364 done accessing resource at 2/28/2013 7:08:01 PM
             *
             * Agent=AgentComputerName1 PID=11396 accessing resource at 2/28/2013 7:07:51 PM
             * Agent=AgentComputerName1 PID=11396 done accessing resource at 2/28/2013 7:07:56 PM
             *
             * Agent=AgentComputerName1 PID=12008 accessing resource at 2/28/2013 7:08:06 PM
             * Agent=AgentComputerName1 PID=12008 done accessing resource at 2/28/2013 7:08:11 PM
             *
             * Agent=AgentComputerName1 PID=11396 accessing resource at 2/28/2013 7:08:11 PM
             * Agent=AgentComputerName1 PID=11396 done accessing resource at 2/28/2013 7:08:16 PM
             *
             * Agent=AgentComputerName1 PID=9364 accessing resource at 2/28/2013 7:08:16 PM
             * Agent=AgentComputerName1 PID=9364 done accessing resource at 2/28/2013 7:08:21 PM
             *
             * Agent=AgentComputerName1 PID=11552 accessing resource at 2/28/2013 7:08:21 PM
             * Agent=AgentComputerName1 PID=11552 done accessing resource at 2/28/2013 7:08:26 PM
             */
        }

        [Serializable]
        class SyncAccessToMachineResourceTask : Task
        {
            public int TaskNumber { get; set; }

            public override void Execute()
            {
                bool firstInstance;
                Mutex mutex = new Mutex(false, "Local\\LockForMachineResource", out firstInstance);

                // Acquire the mutex
                mutex.WaitOne();

                try
                {
                    UserResource();
                }
                finally
                {
                    // Release the Mutex.
                    mutex.ReleaseMutex();
                }
            }

            private void UserResource()
            {
                // Access the resource
                this.SetProperty<string>("resource-start", string.Format("Agent={0} PID={1} accessing resource at {2}", Environment.MachineName, Process.GetCurrentProcess().Id, DateTime.Now));
                Thread.Sleep(5000);
                this.SetProperty<string>("resource-stop", string.Format("Agent={0} PID={1} done accessing resource at {2}", Environment.MachineName, Process.GetCurrentProcess().Id, DateTime.Now));
            }
        }
    }
}

Discussion

A frequently occurring pattern is synchronizing multiple access to a resource on a local machine. That is, only one host per machine should access the resource at a time. Examples include:

  • Updating an entry in the Windows Registry.
  • Writing a file to a common location.
  • Deleting a file or directory from a common location all hosts share.
  • Checking if an expensive operation has been done to make sure it is performed only once.

See Also