Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / July 2007

Tip: Looking for answers? Try searching our database.

Thread Synchronization with ManualResetEvent

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
incrediblesuperdude@gmail.com - 05 Jul 2007 07:53 GMT
Hi Everybody,

I have some understanding problems, about (thread) synchronization.
Hopefully somebody can explain it to me.

I have the following two processes that use the same piece of
hardware. However, they are not allowed to use it at the same time:
Process 1: System.Threading.Thread
Process 2: System.Timers.Timer elapsed event

I have taken two approaches to synchronize the access of these two
processes to the piece of hardware:
1. With Monitor.Enter(this) and Monitor.Exit(this) in a try-finally
block of the hardware code
2. With ManualResetEvent WaitOne(), Reset() and Set() also in a try-
finally block.
Both these methods could not prevent the hardware from getting called
twice.

My own theories why this doesn't work are:
1. Monitor synchronizes different Threads, but an elapsed event runs
on the same thread?
2. Two threads can both call WaitOne() at the same time, before one of
them had the chance to call Reset(). They will both then pass
WaitOne(), because the ManualResetEvent is for both still in the
signaled state.
'
I have written some test code to test situation 2 and indeed there
seems to be a possibility of no synchronization. I have posted the
code below.

Can anybody explain me why this happens, and how I can get a
synchronization for this?

Kind regards,
Gerben Heinen

### CODE ###
using System;
using System.Threading;

namespace ConsoleApplication3
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
        public Class1(){}
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
           Class1 c = new Class1();
            c.Start();
        }

        private Thread thread1,thread2,thread3;
        private ManualResetEvent mre = new ManualResetEvent(true);
        private volatile int cntr = 0;
        private Random random = new Random();

        public void Start()
        {
            thread1 = new Thread(new ThreadStart(worker1));
            thread2 = new Thread(new ThreadStart(worker2));
            thread3 = new Thread(new ThreadStart(worker3));
            thread1.Start();
            thread2.Start();
            thread3.Start();
        }

        private void worker1()
        {
            while(true)
            {
                try
                {
                    Thread.Sleep(random.Next(100,1000));
                    mre.WaitOne();
                    mre.Reset();
//                    Console.WriteLine("worker1 started");
                    cntr++;
                    Thread.Sleep(random.Next(100,1000));
                    cntr--;
                }
                finally
                {
                    mre.Set();
                }
            }
        }

        private void worker2()
        {
            while(true)
            {
                try
                {
                    Thread.Sleep(random.Next(100,1000));
                    mre.WaitOne();
                    mre.Reset();
//                    Console.WriteLine("worker2 started");
                    cntr++;
                    Thread.Sleep(random.Next(100,1000));
                    cntr--;
                }
                finally
                {
                    mre.Set();
                }
            }
        }

        private void worker3()
        {
            while(true)
            {
                if(cntr==2) System.Console.WriteLine("Cntr equals 2");
                Thread.Sleep(10);
            }
        }
    }
}
#######
Michael Nemtsev - 05 Jul 2007 08:56 GMT
Hello incrediblesuperdude@gmail.com,

Why not to use the Mutex for this?
See there http://www.albahari.com/threading/part2.html#_Mutex

---
WBR,  Michael  Nemtsev [.NET/C# MVP].  
My blog: http://spaces.live.com/laflour
Team blog: http://devkids.blogspot.com/

"The greatest danger for most of us is not that our aim is too high and we
miss it, but that it is too low and we reach it" (c) Michelangelo

> Hi Everybody,
>
[quoted text clipped - 4 lines]
>
> hardware. However, they are not allowed to use it at the same time:
Peter Duniho - 05 Jul 2007 17:43 GMT
> My own theories why this doesn't work are:
> 1. Monitor synchronizes different Threads, but an elapsed event runs
> on the same thread?

This theory is incorrect. The Timer will raise its event on a different  
thread.  It has no way to inject the method into an arbitrary thread.  
Even if you were using the Forms.Timer class, which does always raise the  
event on a specific thread, you will never see the event raised while  
executing other code within that thread.  It can't be executed until the  
thread has returned back to the message pump loop (inside .NET).

> 2. Two threads can both call WaitOne() at the same time, before one of
> them had the chance to call Reset(). They will both then pass
> WaitOne(), because the ManualResetEvent is for both still in the
> signaled state.

This is true.  The code you posted has a race condition, where both  
threads can get past the WaitOne() call before the other has a chance to  
reset the event.

You _could_ fix it by using an AutoResetEvent instead, so that as soon as  
one thread successfully passes the wait, the event is automatically reset  
for you.  But that's generally a more appropriate sort of thing where you  
have a specific need to order access (for example, you want the threads to  
strictly alternate between each other).

Not that it wouldn't work in your case either, just that it's more  
complicated and unnecessarily hinders how obvious it is what the code is  
doing.

If all you are trying to do is ensure two different threads aren't  
accessing the same resource at the same time, then the Monitor class you  
tried _is_ a correct solution.  If you didn't get it to work, it's not  
because the Monitor class is unsuitable.

You could also simply use the "lock()" statement, or as Michael suggests,  
use a mutex.

Pete

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.