Tuesday 24 September 2013

ManualResetEvent or AutoResetEvent?

There are many situations when you need to sequence thread access to a resource along with mutual exclusion in a multithreaded application. Or, there are situations when you need to only sequence the tasks which are performed by different threads, a simple example would be like one thread calculates a number and another thread calculates another number and a third thread performs a division of one number by another, of course you would like to get the numbers initialised first before performing the division. So in such situations you can use Manual or AutoResetEvent. For explanation and usage of ResetEvents please refer my previous article Sequencing thread access with ManualResetEvent and AutoResetEvent. In this article I will talk about when to use ManualRsetEvent and when AutoRsetEvent?
In most of the situations both can be used interchangeably. So the question is what is the difference in them? The difference can be visualised very well with the figure below:

Flap Gate

Manual Gate


AutoResetEvent can be visualised as Flap Gate where it opens for one person and closes automatically. So the next person will need to take the permission again to pass through the gate.

ManualResetEvent can be visualised as the Manual Gate where once the gate is opened any number pf people can pass through until the gate is manually closed.

Here is an implementation of the both ResetEvent types:

public class NormalEntry
{    ManualResetEvent mre = new ManualResetEvent(false);
   
public void AllowAccessTo(Person[] persons)
    {

       
Console.WriteLine("Press enter tp open entry for VIP.");
       
Console.ReadLine();
        mre.Set();
       
Console.WriteLine("VIP passed.");
        mre.Reset();
       
Console.WriteLine("Entry closed manually.");
        Thread[] tr = new Thread[4];
        for (int i = 0; i < 4; i++)
        {

           
ParameterizedThreadStart pts = new ParameterizedThreadStart(WaitForAccess);
            tr[i] = new Thread(pts);
            tr[i].Start(persons[i]);
        }

       
Console.WriteLine("Four more person are waiting to enter.");
       
Console.WriteLine("Press enter to let all the people enter.");
        OpenEntryForAll();
    }

   
private void OpenEntryForAll()
    {

       
Thread.Sleep(1000);
       
Console.WriteLine("Entry opened for all.");
        mre.Set();
    }

   
private void WaitForAccess(object obj)
    {
        mre.WaitOne();

       
Person p = (Person)obj;
       
Console.WriteLine(p.Name + " Passed.");
    }
}
public class BarredEntry
{    AutoResetEvent are = new AutoResetEvent(false);
   
public void AllowAccessTo(Person[] persons)
    {

       
Thread[] tr = new Thread[4];
       
for (int i = 0; i < 4; i++)
        {

           
ParameterizedThreadStart pts = new ParameterizedThreadStart(WaitForAccess);
            tr[i] =
new Thread(pts);
            tr[i].Start(persons[i]);
        }
        are.Set();

       
Console.WriteLine("First Person swiped the card.");
    }

   
private void WaitForAccess(object obj)
    {
        are.WaitOne();

       
Person p = (Person)obj;
       
Console.WriteLine(p.Name + " Passed.");
        are.Set();

       
Console.WriteLine("Next Person swiped the card.");
    }
}


public class Person
{
   
public string Name;
}
public class Premises
{
   
Person[] persons = new Person[4] { new Person() { Name = "p1" }, new Person() { Name = "p2" }, new Person() { Name = "p3" }, new                 Person() { Name = "p4" } };
   
public void ManageAccess()
    {

       
NormalEntry ne = new NormalEntry();
        ne.AllowAccessTo(persons);

       
BarredEntry be = new BarredEntry();be.AllowAccessTo(persons);
    }
}


class Program
{    static void Main(string[] args)
   {  
       Premises p = new Premises();
       p.ManageAccess();
   }
}


In the code above the sequence is not maintained only I have only explained the situations where AutoResetEvent fits better than ManulResetEvent.

No comments:

Post a Comment