Pages

Search

Tuesday, February 14, 2012

System.Threading - Classes Examples

System.Threading package has many classes which are to support thread synchronisation.
A class has to be choosed depending on situation, below source explains 7 situations.
AutoResetEvent, ManualResetEvent, Semaphore, Mutex, Monitor, ReadWriterLock, SpinWait

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
static ManualResetEvent objManualResetEvent = null;
static AutoResetEvent objAutoResetEvent = null;
static System.Threading.Timer objTimer = null;

static void Main(string[] args)
{
try
{
//situation like hand shake, only when it is set once
//then the thread executes the block and resets
AutoReset();

//situation like flags, once after signal is given thread
//executes the block unless the signal is reset
ManualReset();

//Option to allow a more than a single thread (limit specified while creating semaphore object)
//to execute block of code
SemaphoreTrail();

//To allow only a single thread to execute a block of code
//another thread cannot execute the block until the current thread
//releases the mutex lock
//generally we use mutex to sync threads accross processes.
//It is heavy weight
MutexTrail();

//To allow only a single thread to execute a block of code
//also this helps to signalng a thread to execute the block by calling wait.
//calling wait will release lock and but will block current thread until it regains the lock.
// the locak can be regained only when the other thread(s) say pulse or pulseall
MonitorTrail();

//when a single write lock is acquired, all the readers will be in wait mode
//when there is one or more reader lock, writer lock wait till all the reader locks are releases.
//note timeouts are mandatory.
ReadWriterLockTrail();

//situations like where a thread has to wait till a funtion returns true, spinwait.spintuntil can be used
SpinUntilStart();
Console.ReadLine();
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
}


#region SpinUntil
static bool blnTest1 = false;
public static void SpinUntilStart()
{
Thread objTh = new Thread(SpinUntilTest);
objTh.Start();
Console.Read();
blnTest1 = true;
Console.ReadLine();
}

public static void SpinUntilTest()
{
Console.WriteLine("Thread started");
Console.WriteLine("Press enter to end thread");
SpinWait.SpinUntil(() => { return blnTest1; });
Console.WriteLine("Thread ended");
}

#endregion

#region ReadWriterLock
static string strFilepath = Application.StartupPath + "/temp.txt";
static ReaderWriterLock objReaderWriterLock = null;
public static void ReadWriterLockTrail()
{
if (File.Exists(strFilepath)) File.Delete(strFilepath);
objReaderWriterLock = new ReaderWriterLock();
for (int i = 0; i < 10; i++)
{
Thread objTh = new Thread(Writer);
objTh.Start();
Thread objTh1 = new Thread(Reader);
objTh1.Start();
}
}
public static void Reader()
{
try
{
objReaderWriterLock.AcquireReaderLock(1000000);
if (File.Exists(strFilepath))
{
Console.WriteLine(File.ReadAllText(strFilepath));
Thread.Sleep(500);
}
objReaderWriterLock.ReleaseReaderLock();
}
catch
{
Console.WriteLine("read lock failed");
return;
}
}
public static void Writer()
{
try
{
objReaderWriterLock.AcquireWriterLock(1000000);
File.AppendAllText(strFilepath, Environment.NewLine + "\n" + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss"));
Thread.Sleep(500);
objReaderWriterLock.ReleaseWriterLock();
}
catch
{
Console.WriteLine("write lock failed");
return;
}
}
#endregion

#region Monitor
static object Object_Monitor = new object();
public static void MonitorTrail()
{
for (int i = 0; i < 100; i++)
{
Thread objTh = new Thread(new ParameterizedThreadStart(mo_MonitorPrintMe));
objTh.Start(i);
}
}

public static void mo_MonitorPrintMe(object id)
{

Monitor.Enter(Object_Monitor);
Console.WriteLine(id);
Monitor.Pulse(Object_Monitor);
Monitor.Wait(Object_Monitor);

//Thread.Sleep(1000);
Console.WriteLine("Done - " + id);
Monitor.Exit(Object_Monitor);

}
#endregion

#region Mutex
static Mutex objMutex = null;

public static void MutexTrail()
{
objMutex = new Mutex(false, "Mut1");
for (int i = 0; i < 10; i++)
{
Thread objTh1 = new Thread(new ParameterizedThreadStart(mt_MutexPrintMe));
objTh1.Start(i);
}
}

public static void mt_MutexPrintMe(object id)
{
objMutex.WaitOne();
Console.WriteLine(id);
Thread.Sleep(500);
objMutex.ReleaseMutex();
}
#endregion

#region Semaphore
static Semaphore objSemaphore = null;
static int semmaxparallel = 10;
public static void SemaphoreTrail()
{
objSemaphore = new Semaphore(semmaxparallel, semmaxparallel, "Sem1");
for (int i = 0; i < semmaxparallel * 10; i++)
{
Thread objTh1 = new Thread(new ParameterizedThreadStart(st_SemPrintMe));
objTh1.Start(i);
}
}
static int semindex = 0;
public static void st_SemPrintMe(object id)
{
objSemaphore.WaitOne();
Console.WriteLine(id);
Interlocked.Increment(ref semindex);
if (Interlocked.CompareExchange(ref semindex, 0, semmaxparallel) == semmaxparallel)
{
Console.WriteLine("Semaphore is full.");
}
Thread.Sleep(2000);
objSemaphore.Release(1);
}
#endregion

#region auto reset
static void AutoReset()
{
objAutoResetEvent = new AutoResetEvent(false);
objTimer = new System.Threading.Timer(new TimerCallback(Timer_Callcack_AR), null, 0, 1000);
Thread objThread = new Thread(aUpdateTime);
objThread.Start();
}
public static void Timer_Callcack_AR(Object ar)
{
objAutoResetEvent.Set();
Console.WriteLine("done");
}
public static int acounter = 0;
public static void aUpdateTime()
{
while (true)
{
if (objAutoResetEvent.WaitOne())
{
acounter++;
Console.WriteLine(acounter);
}
}
}
#endregion

#region manual reset
static void ManualReset()
{
objManualResetEvent = new ManualResetEvent(false);
objTimer = new System.Threading.Timer(new TimerCallback(Timer_Callcack_MR), null, 0, 1000);
Thread objThread = new Thread(mUpdateTime);
objThread.Start();
}
public static void Timer_Callcack_MR(Object ar)
{
objManualResetEvent.Set();
Console.WriteLine("done");
}
public static int mcounter = 0;
public static void mUpdateTime()
{
while (true)
{
if (objManualResetEvent.WaitOne())
{
mcounter++;
Console.WriteLine(mcounter);
}
}
}
#endregion

}
}

No comments:

Post a Comment