15.02.2015 Views

C# 4 and .NET 4

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

synchronization ❘ 527<br />

The Main() method of the program defines arrays of four ManualResetEventSlim objects <strong>and</strong> four<br />

Calculator objects. Every Calculator is initialized in the constructor with a ManualResetEventSlim<br />

object, so that every task gets its own event object to signal when it is completed. Now the TaskFactory<br />

class is used to have different tasks running the calculation.<br />

class Program<br />

{<br />

static void Main()<br />

{<br />

const int taskCount = 4;<br />

var mEvents = new ManualResetEventSlim[taskCount];<br />

var waitH<strong>and</strong>les = new WaitH<strong>and</strong>le[taskCount];<br />

var calcs = new Calculator[taskCount];<br />

TaskFactory taskFactory = new TaskFactory();<br />

for (int i = 0; i < taskCount; i++)<br />

{<br />

mEvents[i] = new ManualResetEventSlim(false);<br />

waitH<strong>and</strong>les[i] = mEvents[i].WaitH<strong>and</strong>le;<br />

calcs[i] = new Calculator(mEvents[i]);<br />

taskFactory.StartNew(calcs[i].Calculation, Tuple.Create(i + 1, i + 3));<br />

}<br />

//...<br />

The WaitH<strong>and</strong>le class is now used to wait for any one of the events in the array. WaitAny() waits until any<br />

one of the events is signaled. In contrast to ManualResetEvent, ManualResetEventSlim does not derive<br />

from WaitH<strong>and</strong>le. That’s why a separate collection of WaitH<strong>and</strong>le objects is kept that is filled from the<br />

WaitH<strong>and</strong>le property of the ManualResetEventSlim class. WaitAny() returns an index value that provides<br />

information about the event that was signaled. The returned value matches the index of the event array that<br />

is passed to WaitAny(). Using this index the information from the signaled event can be read:<br />

}<br />

}<br />

for (int i = 0; i < taskCount; i++)<br />

{<br />

int index = WaitH<strong>and</strong>le.WaitAny(mEvents);<br />

if (index == WaitH<strong>and</strong>le.WaitTimeout)<br />

{<br />

Console.WriteLine("Timeout!!");<br />

}<br />

else<br />

{<br />

mEvents[index].Reset();<br />

Console.WriteLine("finished task for {0}, result: {1}",<br />

index, calcs[index].Result);<br />

}<br />

}<br />

code snippet EventSample/Program.cs<br />

When starting the application, you can see the threads doing the calculation <strong>and</strong> setting the event to inform<br />

the main thread that it can read the result. At r<strong>and</strong>om times, depending on whether the build is a debug<br />

or release build <strong>and</strong> on your hardware, you might see different orders <strong>and</strong> also a different number of threads<br />

from the pool performing tasks. Here, thread 4 was reused from the pool for doing two tasks because it was<br />

fast enough to finish the calculation first:<br />

Task 1 starts calculation<br />

Task 2 starts calculation<br />

Task 2 is ready<br />

Task 3 starts calculation<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!