Multithreading: more on ManualResetEvent

Published Tue, May 19 2009 18:25

[If you’ve just seem a one post sentence, then you’re probably seeing the first Luna’s post :) . She has just managed to publish a one line post while I was checking what was on the TV:)]

In the previous post, we’ve taken a quick glance at how we can use the ManualResetEvent. At the time, I did promise another example which might better illustrate its use. So, let’s suppose that we have a class that needs to perform a lengthy operation to initialize a field. Using a ManualResetEvent might be just what the doctor would order (if he could prescribe something for our multithreaded problems :) ). Let’s start by looking at the class code:

class SlowInitializer {
    private String _someInfoThatIsExpensive;
    private ManualResetEvent _evt = new ManualResetEvent(false); //non signaled
    public String SomeInfoThatIsExpensive {
        get {
            _evt.WaitOne();
            _someInfoThatIsExpensive = DateTime.Now.ToString();
            return _someInfoThatIsExpensive;
        }
    }
    public SlowInitializer() {
        new Thread(() => {
            Console.WriteLine("Starting expensive operation at " + DateTime.Now.ToString());
            Thread.Sleep(2000);
            Console.WriteLine("Ended expensive operation");
            _evt.Set();
        }).Start();
    }
}

As you can see, we have a simple class which needs to perform a lot of work (not sure about you, but sleeping is a lot of work sometimes) to initialize the _someInfoThatIsExpensive field. In this case, we’re using an event to ensure that a consumer will only have access to the field *after* it has been properly initialized. Initialization is performed in the constructor and it’s delegated to another thread (ensuring that the thread where the instance is created will only block if it accesses the SomeInfoThatIsExpensive property before initialization is completed). Suppose you have the following code:

var slow = new SlowInitializer();           
new Thread(
    () => Console.WriteLine(DateTime.Now.ToString() + "- " + slow.SomeInfoThatIsExpensive))
    .Start();
new Thread(
    () => Console.WriteLine(DateTime.Now.ToString() + "- " + slow.SomeInfoThatIsExpensive))
    .Start();
Console.WriteLine(DateTime.Now.ToString() + "- " + slow.SomeInfoThatIsExpensive);
Thread.Sleep(1000);
new Thread(
    () => Console.WriteLine(DateTime.Now.ToString() + "- " + slow.SomeInfoThatIsExpensive))
    .Start();

If you try to run the previous snippet, you should get blocked on the Console.WriteLine that precedes the Thread.Sleep (btw, that Thread.Sleep is only there to show you that the last thread has direct access to the property – ie, it won’t get blocked because the event has already transitioned into the signaled state). The following figure shows the results I got on my machine:

manualreset

Notice the time of execution for the several Console.WriteLine instructions…As you can see, this is a good scenario for the ManualResetEvent type. And that’s all for today. Keep tuned for more on multithreading! (as you can see, I’m still learning, but I’m already hooked on this fascinating topic! :) )

Filed under: ,

Comments

# Rrctfkcq said on Wednesday, June 24, 2009 1:47 PM

89cF9S comment4 ,

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above:  

Search

This Blog

Tags

Community

Archives

Syndication

Email Notifications

News




  • View Luis Abreu's profile on LinkedIn


    Follow me at Twitter

    My books

    Silverlight 4.0: Curso Completo

    ASP.NET 4.0: Curso Completo

    Portuguese LINQ book cover

    Portuguese ASP.NET 3.5 book cover

    Portuguese ASP.NET AJAX book cover

    Portuguese ASP.NET AJAX book cover