threading - Monitor.Wait/Pulse

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Perecli Manole

    threading - Monitor.Wait/Pulse

    I am having some strange thread synchronization problems that require me to
    better understand the intricacies of Monitor.Wait/Pulse.

    I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
    protecting a resource. Thread 2 and 3 also have a SyncLock block protecting
    the same resource and after executing some code in their blocks they both do
    a Monitor.Pulse to hand of the locked resource back to thread 1.

    While thread 1 has the resource locked both thread 2 and 3 are blocked at
    the beginning of their SyncLock waiting for the resource to be released. The
    question is: When thread 1 does a Monitor.Wait what determines the order of
    which thread 2 or 3 is allowed to enter their SyncLock? And if thread 2 gets
    the resource and then releases it with a Monitor.Pulse, will thread 3 then
    get the resource or will thread 1 get it first?

    Thanks
    Perry


  • Casey Kramer

    #2
    RE: threading - Monitor.Wait/Pulse

    Since .Net Managed threads are backed by native operating system thread
    objects, then the operating system decides which thread executes in what
    order based on the time slots it has provided. The only way to influence the
    order of execution is to muck with Thread Priorities, which is generally
    considered a Bad Thing. When Thread1 calls Wait on the monitor object, all
    it is doing is giving up the remainder of it's time slot, and telling the OS
    it can switch to a different thread. The Monitor object adds items to a
    queue whenever they call Wait(), so you can be pretty sure that the waiting
    threads will be signaled in the order they originally executed, but you
    really have no control over when a specific thread will reach that Wait()
    statement.



    "Perecli Manole" wrote:
    [color=blue]
    > I am having some strange thread synchronization problems that require me to
    > better understand the intricacies of Monitor.Wait/Pulse.
    >
    > I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
    > protecting a resource. Thread 2 and 3 also have a SyncLock block protecting
    > the same resource and after executing some code in their blocks they both do
    > a Monitor.Pulse to hand of the locked resource back to thread 1.
    >
    > While thread 1 has the resource locked both thread 2 and 3 are blocked at
    > the beginning of their SyncLock waiting for the resource to be released. The
    > question is: When thread 1 does a Monitor.Wait what determines the order of
    > which thread 2 or 3 is allowed to enter their SyncLock? And if thread 2 gets
    > the resource and then releases it with a Monitor.Pulse, will thread 3 then
    > get the resource or will thread 1 get it first?
    >
    > Thanks
    > Perry
    >
    >
    >[/color]

    Comment

    • Perecli Manole

      #3
      Re: threading - Monitor.Wait/Pulse

      The problem I am having is that both threads 2 and 3 are executing their
      SyncLock block before returning the resource to thread 1. I was under the
      assumption that as soon as either thread 2 or 3 executes its SyncLock block
      (both containing a .Pulse statement) control would be given back to thread 1
      as soon as either thread 2 or 3 is finished but not both. Since thread 2 and
      3 where both waiting at the beginning of the SyncLock statement for the
      resource to be released by thread 1, they seem to both execute before
      relinquishing the resource. How can have either thread 2 or 3 (whichever
      gets there first) execute but not both before the resource is returned to
      thread 1.

      Thanks
      Perry


      "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
      news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...[color=blue]
      > Since .Net Managed threads are backed by native operating system thread
      > objects, then the operating system decides which thread executes in what
      > order based on the time slots it has provided. The only way to influence
      > the
      > order of execution is to muck with Thread Priorities, which is generally
      > considered a Bad Thing. When Thread1 calls Wait on the monitor object,
      > all
      > it is doing is giving up the remainder of it's time slot, and telling the
      > OS
      > it can switch to a different thread. The Monitor object adds items to a
      > queue whenever they call Wait(), so you can be pretty sure that the
      > waiting
      > threads will be signaled in the order they originally executed, but you
      > really have no control over when a specific thread will reach that Wait()
      > statement.
      >
      >
      >
      > "Perecli Manole" wrote:
      >[color=green]
      >> I am having some strange thread synchronization problems that require me
      >> to
      >> better understand the intricacies of Monitor.Wait/Pulse.
      >>
      >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
      >> protecting a resource. Thread 2 and 3 also have a SyncLock block
      >> protecting
      >> the same resource and after executing some code in their blocks they both
      >> do
      >> a Monitor.Pulse to hand of the locked resource back to thread 1.
      >>
      >> While thread 1 has the resource locked both thread 2 and 3 are blocked at
      >> the beginning of their SyncLock waiting for the resource to be released.
      >> The
      >> question is: When thread 1 does a Monitor.Wait what determines the order
      >> of
      >> which thread 2 or 3 is allowed to enter their SyncLock? And if thread 2
      >> gets
      >> the resource and then releases it with a Monitor.Pulse, will thread 3
      >> then
      >> get the resource or will thread 1 get it first?
      >>
      >> Thanks
      >> Perry
      >>
      >>
      >>[/color][/color]


      Comment

      • Perecli Manole

        #4
        Re: threading - Monitor.Wait/Pulse

        Could you also answer the more important last question I posed in my last
        post?

        "And if thread 2 gets the resource and then releases it with a
        Monitor.Pulse, will thread 3 then get the resource or will thread 1 get it
        first?"

        Thanks
        Perry


        "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
        news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...[color=blue]
        > Since .Net Managed threads are backed by native operating system thread
        > objects, then the operating system decides which thread executes in what
        > order based on the time slots it has provided. The only way to influence
        > the
        > order of execution is to muck with Thread Priorities, which is generally
        > considered a Bad Thing. When Thread1 calls Wait on the monitor object,
        > all
        > it is doing is giving up the remainder of it's time slot, and telling the
        > OS
        > it can switch to a different thread. The Monitor object adds items to a
        > queue whenever they call Wait(), so you can be pretty sure that the
        > waiting
        > threads will be signaled in the order they originally executed, but you
        > really have no control over when a specific thread will reach that Wait()
        > statement.
        >
        >
        >
        > "Perecli Manole" wrote:
        >[color=green]
        >> I am having some strange thread synchronization problems that require me
        >> to
        >> better understand the intricacies of Monitor.Wait/Pulse.
        >>
        >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
        >> protecting a resource. Thread 2 and 3 also have a SyncLock block
        >> protecting
        >> the same resource and after executing some code in their blocks they both
        >> do
        >> a Monitor.Pulse to hand of the locked resource back to thread 1.
        >>
        >> While thread 1 has the resource locked both thread 2 and 3 are blocked at
        >> the beginning of their SyncLock waiting for the resource to be released.
        >> The
        >> question is: When thread 1 does a Monitor.Wait what determines the order
        >> of
        >> which thread 2 or 3 is allowed to enter their SyncLock? And if thread 2
        >> gets
        >> the resource and then releases it with a Monitor.Pulse, will thread 3
        >> then
        >> get the resource or will thread 1 get it first?
        >>
        >> Thanks
        >> Perry
        >>
        >>
        >>[/color][/color]


        Comment

        • Casey Kramer

          #5
          Re: threading - Monitor.Wait/Pulse

          Okay, I think I understand more of your issue now. I'll see if I can explain
          generally how Monitor Deals with Wait() and Pulse()/PulseAll() calls:

          Whenever you call Monitor.Wait(), the thread that makes the call gets put
          into a Wait Queue, and releases the lock on the monitored object. At this
          point another thread may acquire the lock, and even call Wait() itself. Once
          a thread calls Pulse() on the Monitor, the first thread in the Wait Queue
          gets moved into the Lock Queue (if you use PulseAll() then all of the threads
          in the Wait Queue get moved to the lock queue). Once the thread that called
          Pulse() is done, the next item in the Lock Queue will get the lock.

          I think the problem your running into comes from the fact that Thread 1 is
          being put in the Lock Queue behind Thread 2 or Thread 3 (depending on which
          got the lock on the object after Thread1 called Wait()).

          I think, to directly answer your question below, that after Thread 2 calls
          Pulse, then Thread 3 will get the object next, followed by Thread 1. At
          least that is assuming the order of the threads is constant, which you can't
          always rely on (see my original response).

          Does that make sense?

          "Perecli Manole" wrote:
          [color=blue]
          > Could you also answer the more important last question I posed in my last
          > post?
          >
          > "And if thread 2 gets the resource and then releases it with a
          > Monitor.Pulse, will thread 3 then get the resource or will thread 1 get it
          > first?"
          >
          > Thanks
          > Perry
          >
          >
          > "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
          > news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...[color=green]
          > > Since .Net Managed threads are backed by native operating system thread
          > > objects, then the operating system decides which thread executes in what
          > > order based on the time slots it has provided. The only way to influence
          > > the
          > > order of execution is to muck with Thread Priorities, which is generally
          > > considered a Bad Thing. When Thread1 calls Wait on the monitor object,
          > > all
          > > it is doing is giving up the remainder of it's time slot, and telling the
          > > OS
          > > it can switch to a different thread. The Monitor object adds items to a
          > > queue whenever they call Wait(), so you can be pretty sure that the
          > > waiting
          > > threads will be signaled in the order they originally executed, but you
          > > really have no control over when a specific thread will reach that Wait()
          > > statement.
          > >
          > >
          > >
          > > "Perecli Manole" wrote:
          > >[color=darkred]
          > >> I am having some strange thread synchronization problems that require me
          > >> to
          > >> better understand the intricacies of Monitor.Wait/Pulse.
          > >>
          > >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
          > >> protecting a resource. Thread 2 and 3 also have a SyncLock block
          > >> protecting
          > >> the same resource and after executing some code in their blocks they both
          > >> do
          > >> a Monitor.Pulse to hand of the locked resource back to thread 1.
          > >>
          > >> While thread 1 has the resource locked both thread 2 and 3 are blocked at
          > >> the beginning of their SyncLock waiting for the resource to be released.
          > >> The
          > >> question is: When thread 1 does a Monitor.Wait what determines the order
          > >> of
          > >> which thread 2 or 3 is allowed to enter their SyncLock? And if thread 2
          > >> gets
          > >> the resource and then releases it with a Monitor.Pulse, will thread 3
          > >> then
          > >> get the resource or will thread 1 get it first?
          > >>
          > >> Thanks
          > >> Perry
          > >>
          > >>
          > >>[/color][/color]
          >
          >
          >[/color]

          Comment

          • Perecli Manole

            #6
            Re: threading - Monitor.Wait/Pulse

            Thank you for the detail description, that explains the unpredictable
            behavior I am experiencing.

            But, in order for my application to work properly, I absolutely need the
            waiting thread (Thread 1) to be the next thread that aquires the lock after
            either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every and
            any pulse from any other thread. How can I achieve this even if it has to be
            done with a different mechanism?

            Thanks
            Perry

            "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
            news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...[color=blue]
            > Okay, I think I understand more of your issue now. I'll see if I can
            > explain
            > generally how Monitor Deals with Wait() and Pulse()/PulseAll() calls:
            >
            > Whenever you call Monitor.Wait(), the thread that makes the call gets put
            > into a Wait Queue, and releases the lock on the monitored object. At this
            > point another thread may acquire the lock, and even call Wait() itself.
            > Once
            > a thread calls Pulse() on the Monitor, the first thread in the Wait Queue
            > gets moved into the Lock Queue (if you use PulseAll() then all of the
            > threads
            > in the Wait Queue get moved to the lock queue). Once the thread that
            > called
            > Pulse() is done, the next item in the Lock Queue will get the lock.
            >
            > I think the problem your running into comes from the fact that Thread 1 is
            > being put in the Lock Queue behind Thread 2 or Thread 3 (depending on
            > which
            > got the lock on the object after Thread1 called Wait()).
            >
            > I think, to directly answer your question below, that after Thread 2 calls
            > Pulse, then Thread 3 will get the object next, followed by Thread 1. At
            > least that is assuming the order of the threads is constant, which you
            > can't
            > always rely on (see my original response).
            >
            > Does that make sense?
            >
            > "Perecli Manole" wrote:
            >[color=green]
            >> Could you also answer the more important last question I posed in my last
            >> post?
            >>
            >> "And if thread 2 gets the resource and then releases it with a
            >> Monitor.Pulse, will thread 3 then get the resource or will thread 1 get
            >> it
            >> first?"
            >>
            >> Thanks
            >> Perry
            >>
            >>
            >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
            >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...[color=darkred]
            >> > Since .Net Managed threads are backed by native operating system thread
            >> > objects, then the operating system decides which thread executes in
            >> > what
            >> > order based on the time slots it has provided. The only way to
            >> > influence
            >> > the
            >> > order of execution is to muck with Thread Priorities, which is
            >> > generally
            >> > considered a Bad Thing. When Thread1 calls Wait on the monitor object,
            >> > all
            >> > it is doing is giving up the remainder of it's time slot, and telling
            >> > the
            >> > OS
            >> > it can switch to a different thread. The Monitor object adds items to
            >> > a
            >> > queue whenever they call Wait(), so you can be pretty sure that the
            >> > waiting
            >> > threads will be signaled in the order they originally executed, but you
            >> > really have no control over when a specific thread will reach that
            >> > Wait()
            >> > statement.
            >> >
            >> >
            >> >
            >> > "Perecli Manole" wrote:
            >> >
            >> >> I am having some strange thread synchronization problems that require
            >> >> me
            >> >> to
            >> >> better understand the intricacies of Monitor.Wait/Pulse.
            >> >>
            >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
            >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
            >> >> protecting
            >> >> the same resource and after executing some code in their blocks they
            >> >> both
            >> >> do
            >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
            >> >>
            >> >> While thread 1 has the resource locked both thread 2 and 3 are blocked
            >> >> at
            >> >> the beginning of their SyncLock waiting for the resource to be
            >> >> released.
            >> >> The
            >> >> question is: When thread 1 does a Monitor.Wait what determines the
            >> >> order
            >> >> of
            >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if thread
            >> >> 2
            >> >> gets
            >> >> the resource and then releases it with a Monitor.Pulse, will thread 3
            >> >> then
            >> >> get the resource or will thread 1 get it first?
            >> >>
            >> >> Thanks
            >> >> Perry
            >> >>
            >> >>
            >> >>[/color]
            >>
            >>
            >>[/color][/color]


            Comment

            • Casey Kramer

              #7
              Re: threading - Monitor.Wait/Pulse

              Well, my first suggestion might be to utilize a WaitHandle derived object
              (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
              provide similar signalling to what is available with the Monitor class, but
              the fact that you can manually reset an event means that other threads which
              may call Wait on the handle will not block on that call until the handle is
              reset.

              For your description, it sounds like you may want to consider creating two
              WaitHandle objects, one for Thread2 and one for Thread3, then in Thread1 call
              the static WaitHandle.Wait Any() passing in an array with both of those
              objects. Once Thread2 or Thread3 signals thier handle (using Set()) then
              Thread1 will pick back up.

              WaitHandle includes WaitOne, which waits for a single WaitHandle object to
              be signaled, WaitAny, which waits for any in an array of WaitHandles to be
              signaled, and WaitAll, which waits for all WaitHandles in an array to be
              signaled. The instances include the Set/Reset methods, but also have a
              SignalAndWait method, which allows you to signal one WaitHandle, and Wait on
              another (as a single operation). It seems like some experimenting with these
              might give you the some decent results.

              Looking at your original post again, it looks like this example from Juval
              Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls this a
              "Rendezvous Helper", and describes it as a way to allow two threads to do
              work independently, and then wait for one another to to complete before
              moving on... For what it is worth here is the code (hope C# is okay):

              public class Rendezvous
              {
              AutoResetEvent m_First = new AutoResetEvent( true);
              AutoResetEvent m_Event1 = new AutoResetEvent( false);
              AutoResetEvent m_Event2 = new AutoResetEvent( false);

              public void Wait( )
              {
              bool first = m_First.WaitOne (TimeSpan.Zero, false);
              if(first)
              {
              WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
              }
              else
              {
              WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
              }
              }
              public void Reset( )
              {
              m_First.Set( );
              }
              }

              Here's a usage sample:

              public class RendezvousDemo
              {
              Rendezvous m_Rendezvous = new Rendezvous( );

              public void ThreadMethod1( )
              {
              //Do some work, then
              m_Rendezvous.Wa it( );
              //Continue executing
              }
              public void ThreadMethod2( )
              {
              //Do some work, then
              m_Rendezvous.Wa it( );
              //Continue executing

              }
              }
              RendezvousDemo demo = new RendezvousDemo( );
              Thread thread1 = new Thread(demo.Thr eadMethod1);
              thread1.Start( );

              Thread thread2 = new Thread(demo.Thr eadMethod2);
              thread2.Start( );

              Basically what this boils down to is that thread1 and thread2 are started,
              and whichever one finishes first is blocked until the other is finished, at
              which point they both continue.

              I'm not sure if the example is too abstract for your needs, but hopefully it
              gives you enough to tinker with.

              "Perecli Manole" wrote:
              [color=blue]
              > Thank you for the detail description, that explains the unpredictable
              > behavior I am experiencing.
              >
              > But, in order for my application to work properly, I absolutely need the
              > waiting thread (Thread 1) to be the next thread that aquires the lock after
              > either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every and
              > any pulse from any other thread. How can I achieve this even if it has to be
              > done with a different mechanism?
              >
              > Thanks
              > Perry
              >
              > "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
              > news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...[color=green]
              > > Okay, I think I understand more of your issue now. I'll see if I can
              > > explain
              > > generally how Monitor Deals with Wait() and Pulse()/PulseAll() calls:
              > >
              > > Whenever you call Monitor.Wait(), the thread that makes the call gets put
              > > into a Wait Queue, and releases the lock on the monitored object. At this
              > > point another thread may acquire the lock, and even call Wait() itself.
              > > Once
              > > a thread calls Pulse() on the Monitor, the first thread in the Wait Queue
              > > gets moved into the Lock Queue (if you use PulseAll() then all of the
              > > threads
              > > in the Wait Queue get moved to the lock queue). Once the thread that
              > > called
              > > Pulse() is done, the next item in the Lock Queue will get the lock.
              > >
              > > I think the problem your running into comes from the fact that Thread 1 is
              > > being put in the Lock Queue behind Thread 2 or Thread 3 (depending on
              > > which
              > > got the lock on the object after Thread1 called Wait()).
              > >
              > > I think, to directly answer your question below, that after Thread 2 calls
              > > Pulse, then Thread 3 will get the object next, followed by Thread 1. At
              > > least that is assuming the order of the threads is constant, which you
              > > can't
              > > always rely on (see my original response).
              > >
              > > Does that make sense?
              > >
              > > "Perecli Manole" wrote:
              > >[color=darkred]
              > >> Could you also answer the more important last question I posed in my last
              > >> post?
              > >>
              > >> "And if thread 2 gets the resource and then releases it with a
              > >> Monitor.Pulse, will thread 3 then get the resource or will thread 1 get
              > >> it
              > >> first?"
              > >>
              > >> Thanks
              > >> Perry
              > >>
              > >>
              > >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
              > >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...
              > >> > Since .Net Managed threads are backed by native operating system thread
              > >> > objects, then the operating system decides which thread executes in
              > >> > what
              > >> > order based on the time slots it has provided. The only way to
              > >> > influence
              > >> > the
              > >> > order of execution is to muck with Thread Priorities, which is
              > >> > generally
              > >> > considered a Bad Thing. When Thread1 calls Wait on the monitor object,
              > >> > all
              > >> > it is doing is giving up the remainder of it's time slot, and telling
              > >> > the
              > >> > OS
              > >> > it can switch to a different thread. The Monitor object adds items to
              > >> > a
              > >> > queue whenever they call Wait(), so you can be pretty sure that the
              > >> > waiting
              > >> > threads will be signaled in the order they originally executed, but you
              > >> > really have no control over when a specific thread will reach that
              > >> > Wait()
              > >> > statement.
              > >> >
              > >> >
              > >> >
              > >> > "Perecli Manole" wrote:
              > >> >
              > >> >> I am having some strange thread synchronization problems that require
              > >> >> me
              > >> >> to
              > >> >> better understand the intricacies of Monitor.Wait/Pulse.
              > >> >>
              > >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
              > >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
              > >> >> protecting
              > >> >> the same resource and after executing some code in their blocks they
              > >> >> both
              > >> >> do
              > >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
              > >> >>
              > >> >> While thread 1 has the resource locked both thread 2 and 3 are blocked
              > >> >> at
              > >> >> the beginning of their SyncLock waiting for the resource to be
              > >> >> released.
              > >> >> The
              > >> >> question is: When thread 1 does a Monitor.Wait what determines the
              > >> >> order
              > >> >> of
              > >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if thread
              > >> >> 2
              > >> >> gets
              > >> >> the resource and then releases it with a Monitor.Pulse, will thread 3
              > >> >> then
              > >> >> get the resource or will thread 1 get it first?
              > >> >>
              > >> >> Thanks
              > >> >> Perry
              > >> >>
              > >> >>
              > >> >>
              > >>
              > >>
              > >>[/color][/color]
              >
              >
              >[/color]

              Comment

              • Perecli Manole

                #8
                Re: threading - Monitor.Wait/Pulse

                I had the same thought as you so I tried the AutoResetEvent. This approach
                has a strange side effect though. The WaitHandle, I'am guessing, seems to
                prevent the SerialPort.Data Received event from fireing so thread 2 and above
                are not being called causing the WaitOne to always expire on the timout.
                When using the Monitor.Wait function instead the event is raised again. Can
                this be explained? Here a snipit that shows the basics:

                'global
                Private _ARE1 As New AutoResetEvent( False)
                Private _ARE2 As New AutoResetEvent( False)

                '---------------------- transmit tread 1 ----------------------
                SyncLock _objTxRxSync
                _objSerialPort. Write(objTxPack et.Bytes, 0, objCurrTxPacket .Bytes.Length)
                _objTxRxSync.As sertedPacket = objTxPacket
                _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                If objTxPacket.Nee dsPacketRespons e Then
                _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                End If
                End If
                End SyncLock

                '------------------receive threads 2,3,n.... ---------------------
                SyncLock _objTxRxSync
                If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                _ARE1.Set()
                Exit Sub
                End If
                End SyncLock

                'do some work that does not need syncronization for non echo packets only
                '..............

                SyncLock _objTxRxSync
                If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                _ARE2.Set()
                End If
                End SyncLock

                RaiseCallBackEv ent(objRxPacket )



                Thanks
                Perry




                "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...[color=blue]
                > Well, my first suggestion might be to utilize a WaitHandle derived object
                > (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
                > provide similar signalling to what is available with the Monitor class,
                > but
                > the fact that you can manually reset an event means that other threads
                > which
                > may call Wait on the handle will not block on that call until the handle
                > is
                > reset.
                >
                > For your description, it sounds like you may want to consider creating two
                > WaitHandle objects, one for Thread2 and one for Thread3, then in Thread1
                > call
                > the static WaitHandle.Wait Any() passing in an array with both of those
                > objects. Once Thread2 or Thread3 signals thier handle (using Set()) then
                > Thread1 will pick back up.
                >
                > WaitHandle includes WaitOne, which waits for a single WaitHandle object to
                > be signaled, WaitAny, which waits for any in an array of WaitHandles to be
                > signaled, and WaitAll, which waits for all WaitHandles in an array to be
                > signaled. The instances include the Set/Reset methods, but also have a
                > SignalAndWait method, which allows you to signal one WaitHandle, and Wait
                > on
                > another (as a single operation). It seems like some experimenting with
                > these
                > might give you the some decent results.
                >
                > Looking at your original post again, it looks like this example from Juval
                > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls
                > this a
                > "Rendezvous Helper", and describes it as a way to allow two threads to do
                > work independently, and then wait for one another to to complete before
                > moving on... For what it is worth here is the code (hope C# is okay):
                >
                > public class Rendezvous
                > {
                > AutoResetEvent m_First = new AutoResetEvent( true);
                > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                >
                > public void Wait( )
                > {
                > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                > if(first)
                > {
                > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                > }
                > else
                > {
                > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                > }
                > }
                > public void Reset( )
                > {
                > m_First.Set( );
                > }
                > }
                >
                > Here's a usage sample:
                >
                > public class RendezvousDemo
                > {
                > Rendezvous m_Rendezvous = new Rendezvous( );
                >
                > public void ThreadMethod1( )
                > {
                > //Do some work, then
                > m_Rendezvous.Wa it( );
                > //Continue executing
                > }
                > public void ThreadMethod2( )
                > {
                > //Do some work, then
                > m_Rendezvous.Wa it( );
                > //Continue executing
                >
                > }
                > }
                > RendezvousDemo demo = new RendezvousDemo( );
                > Thread thread1 = new Thread(demo.Thr eadMethod1);
                > thread1.Start( );
                >
                > Thread thread2 = new Thread(demo.Thr eadMethod2);
                > thread2.Start( );
                >
                > Basically what this boils down to is that thread1 and thread2 are started,
                > and whichever one finishes first is blocked until the other is finished,
                > at
                > which point they both continue.
                >
                > I'm not sure if the example is too abstract for your needs, but hopefully
                > it
                > gives you enough to tinker with.
                >
                > "Perecli Manole" wrote:
                >[color=green]
                >> Thank you for the detail description, that explains the unpredictable
                >> behavior I am experiencing.
                >>
                >> But, in order for my application to work properly, I absolutely need the
                >> waiting thread (Thread 1) to be the next thread that aquires the lock
                >> after
                >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every and
                >> any pulse from any other thread. How can I achieve this even if it has to
                >> be
                >> done with a different mechanism?
                >>
                >> Thanks
                >> Perry
                >>
                >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...[color=darkred]
                >> > Okay, I think I understand more of your issue now. I'll see if I can
                >> > explain
                >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll() calls:
                >> >
                >> > Whenever you call Monitor.Wait(), the thread that makes the call gets
                >> > put
                >> > into a Wait Queue, and releases the lock on the monitored object. At
                >> > this
                >> > point another thread may acquire the lock, and even call Wait() itself.
                >> > Once
                >> > a thread calls Pulse() on the Monitor, the first thread in the Wait
                >> > Queue
                >> > gets moved into the Lock Queue (if you use PulseAll() then all of the
                >> > threads
                >> > in the Wait Queue get moved to the lock queue). Once the thread that
                >> > called
                >> > Pulse() is done, the next item in the Lock Queue will get the lock.
                >> >
                >> > I think the problem your running into comes from the fact that Thread 1
                >> > is
                >> > being put in the Lock Queue behind Thread 2 or Thread 3 (depending on
                >> > which
                >> > got the lock on the object after Thread1 called Wait()).
                >> >
                >> > I think, to directly answer your question below, that after Thread 2
                >> > calls
                >> > Pulse, then Thread 3 will get the object next, followed by Thread 1.
                >> > At
                >> > least that is assuming the order of the threads is constant, which you
                >> > can't
                >> > always rely on (see my original response).
                >> >
                >> > Does that make sense?
                >> >
                >> > "Perecli Manole" wrote:
                >> >
                >> >> Could you also answer the more important last question I posed in my
                >> >> last
                >> >> post?
                >> >>
                >> >> "And if thread 2 gets the resource and then releases it with a
                >> >> Monitor.Pulse, will thread 3 then get the resource or will thread 1
                >> >> get
                >> >> it
                >> >> first?"
                >> >>
                >> >> Thanks
                >> >> Perry
                >> >>
                >> >>
                >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                >> >> message
                >> >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...
                >> >> > Since .Net Managed threads are backed by native operating system
                >> >> > thread
                >> >> > objects, then the operating system decides which thread executes in
                >> >> > what
                >> >> > order based on the time slots it has provided. The only way to
                >> >> > influence
                >> >> > the
                >> >> > order of execution is to muck with Thread Priorities, which is
                >> >> > generally
                >> >> > considered a Bad Thing. When Thread1 calls Wait on the monitor
                >> >> > object,
                >> >> > all
                >> >> > it is doing is giving up the remainder of it's time slot, and
                >> >> > telling
                >> >> > the
                >> >> > OS
                >> >> > it can switch to a different thread. The Monitor object adds items
                >> >> > to
                >> >> > a
                >> >> > queue whenever they call Wait(), so you can be pretty sure that the
                >> >> > waiting
                >> >> > threads will be signaled in the order they originally executed, but
                >> >> > you
                >> >> > really have no control over when a specific thread will reach that
                >> >> > Wait()
                >> >> > statement.
                >> >> >
                >> >> >
                >> >> >
                >> >> > "Perecli Manole" wrote:
                >> >> >
                >> >> >> I am having some strange thread synchronization problems that
                >> >> >> require
                >> >> >> me
                >> >> >> to
                >> >> >> better understand the intricacies of Monitor.Wait/Pulse.
                >> >> >>
                >> >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
                >> >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
                >> >> >> protecting
                >> >> >> the same resource and after executing some code in their blocks
                >> >> >> they
                >> >> >> both
                >> >> >> do
                >> >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
                >> >> >>
                >> >> >> While thread 1 has the resource locked both thread 2 and 3 are
                >> >> >> blocked
                >> >> >> at
                >> >> >> the beginning of their SyncLock waiting for the resource to be
                >> >> >> released.
                >> >> >> The
                >> >> >> question is: When thread 1 does a Monitor.Wait what determines the
                >> >> >> order
                >> >> >> of
                >> >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if
                >> >> >> thread
                >> >> >> 2
                >> >> >> gets
                >> >> >> the resource and then releases it with a Monitor.Pulse, will thread
                >> >> >> 3
                >> >> >> then
                >> >> >> get the resource or will thread 1 get it first?
                >> >> >>
                >> >> >> Thanks
                >> >> >> Perry
                >> >> >>
                >> >> >>
                >> >> >>
                >> >>
                >> >>
                >> >>[/color]
                >>
                >>
                >>[/color][/color]


                Comment

                • Casey Kramer

                  #9
                  Re: threading - Monitor.Wait/Pulse

                  I think the problem is that you are calling the Wait() mehod on your wait
                  handle within your SynLock block. The one thing Monitor.Wait does that you
                  don't get with WaitHandles is that it releases the Lock on the Object you
                  call Wait on.

                  I would say break it out into two SynLock groups in Thread 1, one locking
                  the resources just prior to calling WaitHandle.Wait (), and the other after
                  the Wait returns.

                  You'll need to limit the scope of the SynLock in Thread's 2 & 3 as well.

                  I'm afraid, though, that you may run into a similar problem as the one you
                  were experiencing with the Monitor object. You may want to consider using
                  the Semiphore class to allow 2 classes to access your _objTxRxSync object at
                  a time. You would probably also need to use either a WaitHandle, or a global
                  (and locked) variable to make sure that Threads 2 & 3 don't do their thing
                  until Thread 1 is ready. Adding the Semiphore will give you the ability to
                  make sure only two threads will be working with the resources at a time,
                  though.

                  Does this make any sense?

                  Casey

                  "Perecli Manole" wrote:
                  [color=blue]
                  > I had the same thought as you so I tried the AutoResetEvent. This approach
                  > has a strange side effect though. The WaitHandle, I'am guessing, seems to
                  > prevent the SerialPort.Data Received event from fireing so thread 2 and above
                  > are not being called causing the WaitOne to always expire on the timout.
                  > When using the Monitor.Wait function instead the event is raised again. Can
                  > this be explained? Here a snipit that shows the basics:
                  >
                  > 'global
                  > Private _ARE1 As New AutoResetEvent( False)
                  > Private _ARE2 As New AutoResetEvent( False)
                  >
                  > '---------------------- transmit tread 1 ----------------------
                  > SyncLock _objTxRxSync
                  > _objSerialPort. Write(objTxPack et.Bytes, 0, objCurrTxPacket .Bytes.Length)
                  > _objTxRxSync.As sertedPacket = objTxPacket
                  > _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                  > If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                  > If objTxPacket.Nee dsPacketRespons e Then
                  > _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                  > _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                  > End If
                  > End If
                  > End SyncLock
                  >
                  > '------------------receive threads 2,3,n.... ---------------------
                  > SyncLock _objTxRxSync
                  > If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                  > _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                  > RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                  > _ARE1.Set()
                  > Exit Sub
                  > End If
                  > End SyncLock
                  >
                  > 'do some work that does not need syncronization for non echo packets only
                  > '..............
                  >
                  > SyncLock _objTxRxSync
                  > If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                  > _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                  > _ARE2.Set()
                  > End If
                  > End SyncLock
                  >
                  > RaiseCallBackEv ent(objRxPacket )
                  >
                  >
                  >
                  > Thanks
                  > Perry
                  >
                  >
                  >
                  >
                  > "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                  > news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...[color=green]
                  > > Well, my first suggestion might be to utilize a WaitHandle derived object
                  > > (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
                  > > provide similar signalling to what is available with the Monitor class,
                  > > but
                  > > the fact that you can manually reset an event means that other threads
                  > > which
                  > > may call Wait on the handle will not block on that call until the handle
                  > > is
                  > > reset.
                  > >
                  > > For your description, it sounds like you may want to consider creating two
                  > > WaitHandle objects, one for Thread2 and one for Thread3, then in Thread1
                  > > call
                  > > the static WaitHandle.Wait Any() passing in an array with both of those
                  > > objects. Once Thread2 or Thread3 signals thier handle (using Set()) then
                  > > Thread1 will pick back up.
                  > >
                  > > WaitHandle includes WaitOne, which waits for a single WaitHandle object to
                  > > be signaled, WaitAny, which waits for any in an array of WaitHandles to be
                  > > signaled, and WaitAll, which waits for all WaitHandles in an array to be
                  > > signaled. The instances include the Set/Reset methods, but also have a
                  > > SignalAndWait method, which allows you to signal one WaitHandle, and Wait
                  > > on
                  > > another (as a single operation). It seems like some experimenting with
                  > > these
                  > > might give you the some decent results.
                  > >
                  > > Looking at your original post again, it looks like this example from Juval
                  > > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls
                  > > this a
                  > > "Rendezvous Helper", and describes it as a way to allow two threads to do
                  > > work independently, and then wait for one another to to complete before
                  > > moving on... For what it is worth here is the code (hope C# is okay):
                  > >
                  > > public class Rendezvous
                  > > {
                  > > AutoResetEvent m_First = new AutoResetEvent( true);
                  > > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                  > > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                  > >
                  > > public void Wait( )
                  > > {
                  > > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                  > > if(first)
                  > > {
                  > > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                  > > }
                  > > else
                  > > {
                  > > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                  > > }
                  > > }
                  > > public void Reset( )
                  > > {
                  > > m_First.Set( );
                  > > }
                  > > }
                  > >
                  > > Here's a usage sample:
                  > >
                  > > public class RendezvousDemo
                  > > {
                  > > Rendezvous m_Rendezvous = new Rendezvous( );
                  > >
                  > > public void ThreadMethod1( )
                  > > {
                  > > //Do some work, then
                  > > m_Rendezvous.Wa it( );
                  > > //Continue executing
                  > > }
                  > > public void ThreadMethod2( )
                  > > {
                  > > //Do some work, then
                  > > m_Rendezvous.Wa it( );
                  > > //Continue executing
                  > >
                  > > }
                  > > }
                  > > RendezvousDemo demo = new RendezvousDemo( );
                  > > Thread thread1 = new Thread(demo.Thr eadMethod1);
                  > > thread1.Start( );
                  > >
                  > > Thread thread2 = new Thread(demo.Thr eadMethod2);
                  > > thread2.Start( );
                  > >
                  > > Basically what this boils down to is that thread1 and thread2 are started,
                  > > and whichever one finishes first is blocked until the other is finished,
                  > > at
                  > > which point they both continue.
                  > >
                  > > I'm not sure if the example is too abstract for your needs, but hopefully
                  > > it
                  > > gives you enough to tinker with.
                  > >
                  > > "Perecli Manole" wrote:
                  > >[color=darkred]
                  > >> Thank you for the detail description, that explains the unpredictable
                  > >> behavior I am experiencing.
                  > >>
                  > >> But, in order for my application to work properly, I absolutely need the
                  > >> waiting thread (Thread 1) to be the next thread that aquires the lock
                  > >> after
                  > >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every and
                  > >> any pulse from any other thread. How can I achieve this even if it has to
                  > >> be
                  > >> done with a different mechanism?
                  > >>
                  > >> Thanks
                  > >> Perry
                  > >>
                  > >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                  > >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...
                  > >> > Okay, I think I understand more of your issue now. I'll see if I can
                  > >> > explain
                  > >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll() calls:
                  > >> >
                  > >> > Whenever you call Monitor.Wait(), the thread that makes the call gets
                  > >> > put
                  > >> > into a Wait Queue, and releases the lock on the monitored object. At
                  > >> > this
                  > >> > point another thread may acquire the lock, and even call Wait() itself.
                  > >> > Once
                  > >> > a thread calls Pulse() on the Monitor, the first thread in the Wait
                  > >> > Queue
                  > >> > gets moved into the Lock Queue (if you use PulseAll() then all of the
                  > >> > threads
                  > >> > in the Wait Queue get moved to the lock queue). Once the thread that
                  > >> > called
                  > >> > Pulse() is done, the next item in the Lock Queue will get the lock.
                  > >> >
                  > >> > I think the problem your running into comes from the fact that Thread 1
                  > >> > is
                  > >> > being put in the Lock Queue behind Thread 2 or Thread 3 (depending on
                  > >> > which
                  > >> > got the lock on the object after Thread1 called Wait()).
                  > >> >
                  > >> > I think, to directly answer your question below, that after Thread 2
                  > >> > calls
                  > >> > Pulse, then Thread 3 will get the object next, followed by Thread 1.
                  > >> > At
                  > >> > least that is assuming the order of the threads is constant, which you
                  > >> > can't
                  > >> > always rely on (see my original response).
                  > >> >
                  > >> > Does that make sense?
                  > >> >
                  > >> > "Perecli Manole" wrote:
                  > >> >
                  > >> >> Could you also answer the more important last question I posed in my
                  > >> >> last
                  > >> >> post?
                  > >> >>
                  > >> >> "And if thread 2 gets the resource and then releases it with a
                  > >> >> Monitor.Pulse, will thread 3 then get the resource or will thread 1
                  > >> >> get
                  > >> >> it
                  > >> >> first?"
                  > >> >>
                  > >> >> Thanks
                  > >> >> Perry
                  > >> >>
                  > >> >>
                  > >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                  > >> >> message
                  > >> >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...
                  > >> >> > Since .Net Managed threads are backed by native operating system
                  > >> >> > thread
                  > >> >> > objects, then the operating system decides which thread executes in
                  > >> >> > what
                  > >> >> > order based on the time slots it has provided. The only way to
                  > >> >> > influence
                  > >> >> > the
                  > >> >> > order of execution is to muck with Thread Priorities, which is
                  > >> >> > generally
                  > >> >> > considered a Bad Thing. When Thread1 calls Wait on the monitor
                  > >> >> > object,
                  > >> >> > all
                  > >> >> > it is doing is giving up the remainder of it's time slot, and
                  > >> >> > telling
                  > >> >> > the
                  > >> >> > OS
                  > >> >> > it can switch to a different thread. The Monitor object adds items
                  > >> >> > to
                  > >> >> > a
                  > >> >> > queue whenever they call Wait(), so you can be pretty sure that the
                  > >> >> > waiting
                  > >> >> > threads will be signaled in the order they originally executed, but
                  > >> >> > you
                  > >> >> > really have no control over when a specific thread will reach that
                  > >> >> > Wait()
                  > >> >> > statement.
                  > >> >> >
                  > >> >> >
                  > >> >> >
                  > >> >> > "Perecli Manole" wrote:
                  > >> >> >
                  > >> >> >> I am having some strange thread synchronization problems that
                  > >> >> >> require
                  > >> >> >> me
                  > >> >> >> to
                  > >> >> >> better understand the intricacies of Monitor.Wait/Pulse.
                  > >> >> >>
                  > >> >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock block
                  > >> >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
                  > >> >> >> protecting
                  > >> >> >> the same resource and after executing some code in their blocks
                  > >> >> >> they
                  > >> >> >> both
                  > >> >> >> do
                  > >> >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
                  > >> >> >>
                  > >> >> >> While thread 1 has the resource locked both thread 2 and 3 are
                  > >> >> >> blocked
                  > >> >> >> at
                  > >> >> >> the beginning of their SyncLock waiting for the resource to be
                  > >> >> >> released.
                  > >> >> >> The
                  > >> >> >> question is: When thread 1 does a Monitor.Wait what determines the
                  > >> >> >> order
                  > >> >> >> of
                  > >> >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if
                  > >> >> >> thread
                  > >> >> >> 2
                  > >> >> >> gets
                  > >> >> >> the resource and then releases it with a Monitor.Pulse, will thread
                  > >> >> >> 3
                  > >> >> >> then
                  > >> >> >> get the resource or will thread 1 get it first?
                  > >> >> >>
                  > >> >> >> Thanks
                  > >> >> >> Perry
                  > >> >> >>
                  > >> >> >>
                  > >> >> >>
                  > >> >>
                  > >> >>
                  > >> >>
                  > >>
                  > >>
                  > >>[/color][/color]
                  >
                  >
                  >[/color]

                  Comment

                  • Perecli Manole

                    #10
                    Re: threading - Monitor.Wait/Pulse

                    >I think the problem is that you are calling the Wait() mehod on your wait[color=blue]
                    > handle within your SynLock block. The one thing Monitor.Wait does that
                    > you
                    > don't get with WaitHandles is that it releases the Lock on the Object you
                    > call Wait on.[/color]

                    I thought by setting the last boolean parameter in the WaitOne method to
                    True will allow the exit of the locking context. The documentation seems to
                    imply this.
                    _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True)

                    [color=blue]
                    > I would say break it out into two SynLock groups in Thread 1, one locking
                    > the resources just prior to calling WaitHandle.Wait (), and the other after
                    > the Wait returns.[/color]

                    If I break the SyncLock into two groups then the memebers of the objTxPacket
                    can be changed by other threads in between the SyncLocks. Also don't know
                    how to synclock the second WaitOne because it is in a conditional statement
                    that get its value from the locked object. It the object is not locked at
                    that point then there could be problems.

                    SyncLock _objTxRxSync
                    _objSerialPort. Write(objTxPack et.Bytes, 0, objCurrTxPacket .Bytes.Length)
                    _objTxRxSync.As sertedPacket = objTxPacket
                    _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                    If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                    If objTxPacket.Nee dsPacketRespons e Then
                    _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                    _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                    End If
                    End If
                    End SyncLock

                    [color=blue]
                    > You'll need to limit the scope of the SynLock in Thread's 2 & 3 as well.[/color]

                    How can I limit it any smaller that it already is?
                    [color=blue]
                    > I'm afraid, though, that you may run into a similar problem as the one you
                    > were experiencing with the Monitor object. You may want to consider using
                    > the Semiphore class to allow 2 classes to access your _objTxRxSync object
                    > at
                    > a time. You would probably also need to use either a WaitHandle, or a
                    > global
                    > (and locked) variable to make sure that Threads 2 & 3 don't do their thing
                    > until Thread 1 is ready. Adding the Semiphore will give you the ability
                    > to
                    > make sure only two threads will be working with the resources at a time,
                    > though.
                    >Does this make any sense?[/color]

                    Not clear how to do this.

                    Perry


                    [color=blue]
                    > "Perecli Manole" wrote:
                    >[color=green]
                    >> I had the same thought as you so I tried the AutoResetEvent. This
                    >> approach
                    >> has a strange side effect though. The WaitHandle, I'am guessing, seems to
                    >> prevent the SerialPort.Data Received event from fireing so thread 2 and
                    >> above
                    >> are not being called causing the WaitOne to always expire on the timout.
                    >> When using the Monitor.Wait function instead the event is raised again.
                    >> Can
                    >> this be explained? Here a snipit that shows the basics:
                    >>
                    >> 'global
                    >> Private _ARE1 As New AutoResetEvent( False)
                    >> Private _ARE2 As New AutoResetEvent( False)
                    >>
                    >> '---------------------- transmit tread 1 ----------------------
                    >> SyncLock _objTxRxSync
                    >> _objSerialPort. Write(objTxPack et.Bytes, 0,
                    >> objCurrTxPacket .Bytes.Length)
                    >> _objTxRxSync.As sertedPacket = objTxPacket
                    >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                    >> If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                    >> If objTxPacket.Nee dsPacketRespons e Then
                    >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                    >> _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                    >> End If
                    >> End If
                    >> End SyncLock
                    >>
                    >> '------------------receive threads 2,3,n.... ---------------------
                    >> SyncLock _objTxRxSync
                    >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                    >> _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                    >> RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                    >> _ARE1.Set()
                    >> Exit Sub
                    >> End If
                    >> End SyncLock
                    >>
                    >> 'do some work that does not need syncronization for non echo packets only
                    >> '..............
                    >>
                    >> SyncLock _objTxRxSync
                    >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                    >> _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                    >> _ARE2.Set()
                    >> End If
                    >> End SyncLock
                    >>
                    >> RaiseCallBackEv ent(objRxPacket )
                    >>
                    >>
                    >>
                    >> Thanks
                    >> Perry
                    >>
                    >>
                    >>
                    >>
                    >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                    >> news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...[color=darkred]
                    >> > Well, my first suggestion might be to utilize a WaitHandle derived
                    >> > object
                    >> > (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
                    >> > provide similar signalling to what is available with the Monitor class,
                    >> > but
                    >> > the fact that you can manually reset an event means that other threads
                    >> > which
                    >> > may call Wait on the handle will not block on that call until the
                    >> > handle
                    >> > is
                    >> > reset.
                    >> >
                    >> > For your description, it sounds like you may want to consider creating
                    >> > two
                    >> > WaitHandle objects, one for Thread2 and one for Thread3, then in
                    >> > Thread1
                    >> > call
                    >> > the static WaitHandle.Wait Any() passing in an array with both of those
                    >> > objects. Once Thread2 or Thread3 signals thier handle (using Set())
                    >> > then
                    >> > Thread1 will pick back up.
                    >> >
                    >> > WaitHandle includes WaitOne, which waits for a single WaitHandle object
                    >> > to
                    >> > be signaled, WaitAny, which waits for any in an array of WaitHandles to
                    >> > be
                    >> > signaled, and WaitAll, which waits for all WaitHandles in an array to
                    >> > be
                    >> > signaled. The instances include the Set/Reset methods, but also have a
                    >> > SignalAndWait method, which allows you to signal one WaitHandle, and
                    >> > Wait
                    >> > on
                    >> > another (as a single operation). It seems like some experimenting with
                    >> > these
                    >> > might give you the some decent results.
                    >> >
                    >> > Looking at your original post again, it looks like this example from
                    >> > Juval
                    >> > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls
                    >> > this a
                    >> > "Rendezvous Helper", and describes it as a way to allow two threads to
                    >> > do
                    >> > work independently, and then wait for one another to to complete before
                    >> > moving on... For what it is worth here is the code (hope C# is okay):
                    >> >
                    >> > public class Rendezvous
                    >> > {
                    >> > AutoResetEvent m_First = new AutoResetEvent( true);
                    >> > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                    >> > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                    >> >
                    >> > public void Wait( )
                    >> > {
                    >> > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                    >> > if(first)
                    >> > {
                    >> > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                    >> > }
                    >> > else
                    >> > {
                    >> > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                    >> > }
                    >> > }
                    >> > public void Reset( )
                    >> > {
                    >> > m_First.Set( );
                    >> > }
                    >> > }
                    >> >
                    >> > Here's a usage sample:
                    >> >
                    >> > public class RendezvousDemo
                    >> > {
                    >> > Rendezvous m_Rendezvous = new Rendezvous( );
                    >> >
                    >> > public void ThreadMethod1( )
                    >> > {
                    >> > //Do some work, then
                    >> > m_Rendezvous.Wa it( );
                    >> > //Continue executing
                    >> > }
                    >> > public void ThreadMethod2( )
                    >> > {
                    >> > //Do some work, then
                    >> > m_Rendezvous.Wa it( );
                    >> > //Continue executing
                    >> >
                    >> > }
                    >> > }
                    >> > RendezvousDemo demo = new RendezvousDemo( );
                    >> > Thread thread1 = new Thread(demo.Thr eadMethod1);
                    >> > thread1.Start( );
                    >> >
                    >> > Thread thread2 = new Thread(demo.Thr eadMethod2);
                    >> > thread2.Start( );
                    >> >
                    >> > Basically what this boils down to is that thread1 and thread2 are
                    >> > started,
                    >> > and whichever one finishes first is blocked until the other is
                    >> > finished,
                    >> > at
                    >> > which point they both continue.
                    >> >
                    >> > I'm not sure if the example is too abstract for your needs, but
                    >> > hopefully
                    >> > it
                    >> > gives you enough to tinker with.
                    >> >
                    >> > "Perecli Manole" wrote:
                    >> >
                    >> >> Thank you for the detail description, that explains the unpredictable
                    >> >> behavior I am experiencing.
                    >> >>
                    >> >> But, in order for my application to work properly, I absolutely need
                    >> >> the
                    >> >> waiting thread (Thread 1) to be the next thread that aquires the lock
                    >> >> after
                    >> >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every
                    >> >> and
                    >> >> any pulse from any other thread. How can I achieve this even if it has
                    >> >> to
                    >> >> be
                    >> >> done with a different mechanism?
                    >> >>
                    >> >> Thanks
                    >> >> Perry
                    >> >>
                    >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                    >> >> message
                    >> >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...
                    >> >> > Okay, I think I understand more of your issue now. I'll see if I
                    >> >> > can
                    >> >> > explain
                    >> >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll()
                    >> >> > calls:
                    >> >> >
                    >> >> > Whenever you call Monitor.Wait(), the thread that makes the call
                    >> >> > gets
                    >> >> > put
                    >> >> > into a Wait Queue, and releases the lock on the monitored object.
                    >> >> > At
                    >> >> > this
                    >> >> > point another thread may acquire the lock, and even call Wait()
                    >> >> > itself.
                    >> >> > Once
                    >> >> > a thread calls Pulse() on the Monitor, the first thread in the Wait
                    >> >> > Queue
                    >> >> > gets moved into the Lock Queue (if you use PulseAll() then all of
                    >> >> > the
                    >> >> > threads
                    >> >> > in the Wait Queue get moved to the lock queue). Once the thread
                    >> >> > that
                    >> >> > called
                    >> >> > Pulse() is done, the next item in the Lock Queue will get the lock.
                    >> >> >
                    >> >> > I think the problem your running into comes from the fact that
                    >> >> > Thread 1
                    >> >> > is
                    >> >> > being put in the Lock Queue behind Thread 2 or Thread 3 (depending
                    >> >> > on
                    >> >> > which
                    >> >> > got the lock on the object after Thread1 called Wait()).
                    >> >> >
                    >> >> > I think, to directly answer your question below, that after Thread 2
                    >> >> > calls
                    >> >> > Pulse, then Thread 3 will get the object next, followed by Thread 1.
                    >> >> > At
                    >> >> > least that is assuming the order of the threads is constant, which
                    >> >> > you
                    >> >> > can't
                    >> >> > always rely on (see my original response).
                    >> >> >
                    >> >> > Does that make sense?
                    >> >> >
                    >> >> > "Perecli Manole" wrote:
                    >> >> >
                    >> >> >> Could you also answer the more important last question I posed in
                    >> >> >> my
                    >> >> >> last
                    >> >> >> post?
                    >> >> >>
                    >> >> >> "And if thread 2 gets the resource and then releases it with a
                    >> >> >> Monitor.Pulse, will thread 3 then get the resource or will thread 1
                    >> >> >> get
                    >> >> >> it
                    >> >> >> first?"
                    >> >> >>
                    >> >> >> Thanks
                    >> >> >> Perry
                    >> >> >>
                    >> >> >>
                    >> >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                    >> >> >> message
                    >> >> >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...
                    >> >> >> > Since .Net Managed threads are backed by native operating system
                    >> >> >> > thread
                    >> >> >> > objects, then the operating system decides which thread executes
                    >> >> >> > in
                    >> >> >> > what
                    >> >> >> > order based on the time slots it has provided. The only way to
                    >> >> >> > influence
                    >> >> >> > the
                    >> >> >> > order of execution is to muck with Thread Priorities, which is
                    >> >> >> > generally
                    >> >> >> > considered a Bad Thing. When Thread1 calls Wait on the monitor
                    >> >> >> > object,
                    >> >> >> > all
                    >> >> >> > it is doing is giving up the remainder of it's time slot, and
                    >> >> >> > telling
                    >> >> >> > the
                    >> >> >> > OS
                    >> >> >> > it can switch to a different thread. The Monitor object adds
                    >> >> >> > items
                    >> >> >> > to
                    >> >> >> > a
                    >> >> >> > queue whenever they call Wait(), so you can be pretty sure that
                    >> >> >> > the
                    >> >> >> > waiting
                    >> >> >> > threads will be signaled in the order they originally executed,
                    >> >> >> > but
                    >> >> >> > you
                    >> >> >> > really have no control over when a specific thread will reach
                    >> >> >> > that
                    >> >> >> > Wait()
                    >> >> >> > statement.
                    >> >> >> >
                    >> >> >> >
                    >> >> >> >
                    >> >> >> > "Perecli Manole" wrote:
                    >> >> >> >
                    >> >> >> >> I am having some strange thread synchronization problems that
                    >> >> >> >> require
                    >> >> >> >> me
                    >> >> >> >> to
                    >> >> >> >> better understand the intricacies of Monitor.Wait/Pulse.
                    >> >> >> >>
                    >> >> >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock
                    >> >> >> >> block
                    >> >> >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
                    >> >> >> >> protecting
                    >> >> >> >> the same resource and after executing some code in their blocks
                    >> >> >> >> they
                    >> >> >> >> both
                    >> >> >> >> do
                    >> >> >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
                    >> >> >> >>
                    >> >> >> >> While thread 1 has the resource locked both thread 2 and 3 are
                    >> >> >> >> blocked
                    >> >> >> >> at
                    >> >> >> >> the beginning of their SyncLock waiting for the resource to be
                    >> >> >> >> released.
                    >> >> >> >> The
                    >> >> >> >> question is: When thread 1 does a Monitor.Wait what determines
                    >> >> >> >> the
                    >> >> >> >> order
                    >> >> >> >> of
                    >> >> >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if
                    >> >> >> >> thread
                    >> >> >> >> 2
                    >> >> >> >> gets
                    >> >> >> >> the resource and then releases it with a Monitor.Pulse, will
                    >> >> >> >> thread
                    >> >> >> >> 3
                    >> >> >> >> then
                    >> >> >> >> get the resource or will thread 1 get it first?
                    >> >> >> >>
                    >> >> >> >> Thanks
                    >> >> >> >> Perry
                    >> >> >> >>
                    >> >> >> >>
                    >> >> >> >>
                    >> >> >>
                    >> >> >>
                    >> >> >>
                    >> >>
                    >> >>
                    >> >>[/color]
                    >>
                    >>
                    >>[/color][/color]


                    Comment

                    • Perecli Manole

                      #11
                      Re: threading - Monitor.Wait/Pulse

                      I figured out a solution that is surprisingly simple.
                      Apparently if you do a Thread.Sleep(0) , at the beginning of each thread 2 or
                      3 iteration (before the first SyncLock on those threads), the framework
                      assumes for a brief period that there are no more tasks to follow and gives
                      a time slice back to the waiting thread that was pulsed, rather than taking
                      on another lock request from thread 2 or 3.

                      The Sleep() seems to behave similar to DoEvents() in the UI context.
                      With this approach I can keep using the Monitor.Wait/Pulse which buys me the
                      context unlocking.

                      Thank you for all your help. It definitely got ideas steering in my head by
                      understanding what is really happening.

                      Perry


                      "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                      news:07254588-1E21-4711-954D-F9C7DFDB4859@mi crosoft.com...[color=blue]
                      >I think the problem is that you are calling the Wait() mehod on your wait
                      > handle within your SynLock block. The one thing Monitor.Wait does that
                      > you
                      > don't get with WaitHandles is that it releases the Lock on the Object you
                      > call Wait on.
                      >
                      > I would say break it out into two SynLock groups in Thread 1, one locking
                      > the resources just prior to calling WaitHandle.Wait (), and the other after
                      > the Wait returns.
                      >
                      > You'll need to limit the scope of the SynLock in Thread's 2 & 3 as well.
                      >
                      > I'm afraid, though, that you may run into a similar problem as the one you
                      > were experiencing with the Monitor object. You may want to consider using
                      > the Semiphore class to allow 2 classes to access your _objTxRxSync object
                      > at
                      > a time. You would probably also need to use either a WaitHandle, or a
                      > global
                      > (and locked) variable to make sure that Threads 2 & 3 don't do their thing
                      > until Thread 1 is ready. Adding the Semiphore will give you the ability
                      > to
                      > make sure only two threads will be working with the resources at a time,
                      > though.
                      >
                      > Does this make any sense?
                      >
                      > Casey
                      >
                      > "Perecli Manole" wrote:
                      >[color=green]
                      >> I had the same thought as you so I tried the AutoResetEvent. This
                      >> approach
                      >> has a strange side effect though. The WaitHandle, I'am guessing, seems to
                      >> prevent the SerialPort.Data Received event from fireing so thread 2 and
                      >> above
                      >> are not being called causing the WaitOne to always expire on the timout.
                      >> When using the Monitor.Wait function instead the event is raised again.
                      >> Can
                      >> this be explained? Here a snipit that shows the basics:
                      >>
                      >> 'global
                      >> Private _ARE1 As New AutoResetEvent( False)
                      >> Private _ARE2 As New AutoResetEvent( False)
                      >>
                      >> '---------------------- transmit tread 1 ----------------------
                      >> SyncLock _objTxRxSync
                      >> _objSerialPort. Write(objTxPack et.Bytes, 0,
                      >> objCurrTxPacket .Bytes.Length)
                      >> _objTxRxSync.As sertedPacket = objTxPacket
                      >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                      >> If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                      >> If objTxPacket.Nee dsPacketRespons e Then
                      >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                      >> _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                      >> End If
                      >> End If
                      >> End SyncLock
                      >>
                      >> '------------------receive threads 2,3,n.... ---------------------
                      >> SyncLock _objTxRxSync
                      >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                      >> _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                      >> RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                      >> _ARE1.Set()
                      >> Exit Sub
                      >> End If
                      >> End SyncLock
                      >>
                      >> 'do some work that does not need syncronization for non echo packets only
                      >> '..............
                      >>
                      >> SyncLock _objTxRxSync
                      >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                      >> _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                      >> _ARE2.Set()
                      >> End If
                      >> End SyncLock
                      >>
                      >> RaiseCallBackEv ent(objRxPacket )
                      >>
                      >>
                      >>
                      >> Thanks
                      >> Perry
                      >>
                      >>
                      >>
                      >>
                      >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                      >> news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...[color=darkred]
                      >> > Well, my first suggestion might be to utilize a WaitHandle derived
                      >> > object
                      >> > (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
                      >> > provide similar signalling to what is available with the Monitor class,
                      >> > but
                      >> > the fact that you can manually reset an event means that other threads
                      >> > which
                      >> > may call Wait on the handle will not block on that call until the
                      >> > handle
                      >> > is
                      >> > reset.
                      >> >
                      >> > For your description, it sounds like you may want to consider creating
                      >> > two
                      >> > WaitHandle objects, one for Thread2 and one for Thread3, then in
                      >> > Thread1
                      >> > call
                      >> > the static WaitHandle.Wait Any() passing in an array with both of those
                      >> > objects. Once Thread2 or Thread3 signals thier handle (using Set())
                      >> > then
                      >> > Thread1 will pick back up.
                      >> >
                      >> > WaitHandle includes WaitOne, which waits for a single WaitHandle object
                      >> > to
                      >> > be signaled, WaitAny, which waits for any in an array of WaitHandles to
                      >> > be
                      >> > signaled, and WaitAll, which waits for all WaitHandles in an array to
                      >> > be
                      >> > signaled. The instances include the Set/Reset methods, but also have a
                      >> > SignalAndWait method, which allows you to signal one WaitHandle, and
                      >> > Wait
                      >> > on
                      >> > another (as a single operation). It seems like some experimenting with
                      >> > these
                      >> > might give you the some decent results.
                      >> >
                      >> > Looking at your original post again, it looks like this example from
                      >> > Juval
                      >> > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls
                      >> > this a
                      >> > "Rendezvous Helper", and describes it as a way to allow two threads to
                      >> > do
                      >> > work independently, and then wait for one another to to complete before
                      >> > moving on... For what it is worth here is the code (hope C# is okay):
                      >> >
                      >> > public class Rendezvous
                      >> > {
                      >> > AutoResetEvent m_First = new AutoResetEvent( true);
                      >> > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                      >> > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                      >> >
                      >> > public void Wait( )
                      >> > {
                      >> > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                      >> > if(first)
                      >> > {
                      >> > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                      >> > }
                      >> > else
                      >> > {
                      >> > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                      >> > }
                      >> > }
                      >> > public void Reset( )
                      >> > {
                      >> > m_First.Set( );
                      >> > }
                      >> > }
                      >> >
                      >> > Here's a usage sample:
                      >> >
                      >> > public class RendezvousDemo
                      >> > {
                      >> > Rendezvous m_Rendezvous = new Rendezvous( );
                      >> >
                      >> > public void ThreadMethod1( )
                      >> > {
                      >> > //Do some work, then
                      >> > m_Rendezvous.Wa it( );
                      >> > //Continue executing
                      >> > }
                      >> > public void ThreadMethod2( )
                      >> > {
                      >> > //Do some work, then
                      >> > m_Rendezvous.Wa it( );
                      >> > //Continue executing
                      >> >
                      >> > }
                      >> > }
                      >> > RendezvousDemo demo = new RendezvousDemo( );
                      >> > Thread thread1 = new Thread(demo.Thr eadMethod1);
                      >> > thread1.Start( );
                      >> >
                      >> > Thread thread2 = new Thread(demo.Thr eadMethod2);
                      >> > thread2.Start( );
                      >> >
                      >> > Basically what this boils down to is that thread1 and thread2 are
                      >> > started,
                      >> > and whichever one finishes first is blocked until the other is
                      >> > finished,
                      >> > at
                      >> > which point they both continue.
                      >> >
                      >> > I'm not sure if the example is too abstract for your needs, but
                      >> > hopefully
                      >> > it
                      >> > gives you enough to tinker with.
                      >> >
                      >> > "Perecli Manole" wrote:
                      >> >
                      >> >> Thank you for the detail description, that explains the unpredictable
                      >> >> behavior I am experiencing.
                      >> >>
                      >> >> But, in order for my application to work properly, I absolutely need
                      >> >> the
                      >> >> waiting thread (Thread 1) to be the next thread that aquires the lock
                      >> >> after
                      >> >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every
                      >> >> and
                      >> >> any pulse from any other thread. How can I achieve this even if it has
                      >> >> to
                      >> >> be
                      >> >> done with a different mechanism?
                      >> >>
                      >> >> Thanks
                      >> >> Perry
                      >> >>
                      >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                      >> >> message
                      >> >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...
                      >> >> > Okay, I think I understand more of your issue now. I'll see if I
                      >> >> > can
                      >> >> > explain
                      >> >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll()
                      >> >> > calls:
                      >> >> >
                      >> >> > Whenever you call Monitor.Wait(), the thread that makes the call
                      >> >> > gets
                      >> >> > put
                      >> >> > into a Wait Queue, and releases the lock on the monitored object.
                      >> >> > At
                      >> >> > this
                      >> >> > point another thread may acquire the lock, and even call Wait()
                      >> >> > itself.
                      >> >> > Once
                      >> >> > a thread calls Pulse() on the Monitor, the first thread in the Wait
                      >> >> > Queue
                      >> >> > gets moved into the Lock Queue (if you use PulseAll() then all of
                      >> >> > the
                      >> >> > threads
                      >> >> > in the Wait Queue get moved to the lock queue). Once the thread
                      >> >> > that
                      >> >> > called
                      >> >> > Pulse() is done, the next item in the Lock Queue will get the lock.
                      >> >> >
                      >> >> > I think the problem your running into comes from the fact that
                      >> >> > Thread 1
                      >> >> > is
                      >> >> > being put in the Lock Queue behind Thread 2 or Thread 3 (depending
                      >> >> > on
                      >> >> > which
                      >> >> > got the lock on the object after Thread1 called Wait()).
                      >> >> >
                      >> >> > I think, to directly answer your question below, that after Thread 2
                      >> >> > calls
                      >> >> > Pulse, then Thread 3 will get the object next, followed by Thread 1.
                      >> >> > At
                      >> >> > least that is assuming the order of the threads is constant, which
                      >> >> > you
                      >> >> > can't
                      >> >> > always rely on (see my original response).
                      >> >> >
                      >> >> > Does that make sense?
                      >> >> >
                      >> >> > "Perecli Manole" wrote:
                      >> >> >
                      >> >> >> Could you also answer the more important last question I posed in
                      >> >> >> my
                      >> >> >> last
                      >> >> >> post?
                      >> >> >>
                      >> >> >> "And if thread 2 gets the resource and then releases it with a
                      >> >> >> Monitor.Pulse, will thread 3 then get the resource or will thread 1
                      >> >> >> get
                      >> >> >> it
                      >> >> >> first?"
                      >> >> >>
                      >> >> >> Thanks
                      >> >> >> Perry
                      >> >> >>
                      >> >> >>
                      >> >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                      >> >> >> message
                      >> >> >> news:F3FBD9CB-D15B-4CC8-9B4B-2BA6748A8AD6@mi crosoft.com...
                      >> >> >> > Since .Net Managed threads are backed by native operating system
                      >> >> >> > thread
                      >> >> >> > objects, then the operating system decides which thread executes
                      >> >> >> > in
                      >> >> >> > what
                      >> >> >> > order based on the time slots it has provided. The only way to
                      >> >> >> > influence
                      >> >> >> > the
                      >> >> >> > order of execution is to muck with Thread Priorities, which is
                      >> >> >> > generally
                      >> >> >> > considered a Bad Thing. When Thread1 calls Wait on the monitor
                      >> >> >> > object,
                      >> >> >> > all
                      >> >> >> > it is doing is giving up the remainder of it's time slot, and
                      >> >> >> > telling
                      >> >> >> > the
                      >> >> >> > OS
                      >> >> >> > it can switch to a different thread. The Monitor object adds
                      >> >> >> > items
                      >> >> >> > to
                      >> >> >> > a
                      >> >> >> > queue whenever they call Wait(), so you can be pretty sure that
                      >> >> >> > the
                      >> >> >> > waiting
                      >> >> >> > threads will be signaled in the order they originally executed,
                      >> >> >> > but
                      >> >> >> > you
                      >> >> >> > really have no control over when a specific thread will reach
                      >> >> >> > that
                      >> >> >> > Wait()
                      >> >> >> > statement.
                      >> >> >> >
                      >> >> >> >
                      >> >> >> >
                      >> >> >> > "Perecli Manole" wrote:
                      >> >> >> >
                      >> >> >> >> I am having some strange thread synchronization problems that
                      >> >> >> >> require
                      >> >> >> >> me
                      >> >> >> >> to
                      >> >> >> >> better understand the intricacies of Monitor.Wait/Pulse.
                      >> >> >> >>
                      >> >> >> >> I have 3 threads. Thread 1 does a Monitor.Wait in a SyncLock
                      >> >> >> >> block
                      >> >> >> >> protecting a resource. Thread 2 and 3 also have a SyncLock block
                      >> >> >> >> protecting
                      >> >> >> >> the same resource and after executing some code in their blocks
                      >> >> >> >> they
                      >> >> >> >> both
                      >> >> >> >> do
                      >> >> >> >> a Monitor.Pulse to hand of the locked resource back to thread 1.
                      >> >> >> >>
                      >> >> >> >> While thread 1 has the resource locked both thread 2 and 3 are
                      >> >> >> >> blocked
                      >> >> >> >> at
                      >> >> >> >> the beginning of their SyncLock waiting for the resource to be
                      >> >> >> >> released.
                      >> >> >> >> The
                      >> >> >> >> question is: When thread 1 does a Monitor.Wait what determines
                      >> >> >> >> the
                      >> >> >> >> order
                      >> >> >> >> of
                      >> >> >> >> which thread 2 or 3 is allowed to enter their SyncLock? And if
                      >> >> >> >> thread
                      >> >> >> >> 2
                      >> >> >> >> gets
                      >> >> >> >> the resource and then releases it with a Monitor.Pulse, will
                      >> >> >> >> thread
                      >> >> >> >> 3
                      >> >> >> >> then
                      >> >> >> >> get the resource or will thread 1 get it first?
                      >> >> >> >>
                      >> >> >> >> Thanks
                      >> >> >> >> Perry
                      >> >> >> >>
                      >> >> >> >>
                      >> >> >> >>
                      >> >> >>
                      >> >> >>
                      >> >> >>
                      >> >>
                      >> >>
                      >> >>[/color]
                      >>
                      >>
                      >>[/color][/color]


                      Comment

                      • Casey Kramer

                        #12
                        Re: threading - Monitor.Wait/Pulse

                        That is true....The Sleep() call basically tells the OS that the thread is
                        done with it's time slot for now. I can say that officially, using Sleep for
                        thread synchronization is considered a "Bad Thing" since there is no way to
                        know for sure that the threads are getting started in a particular
                        order....In reality, though, if your creating the thread objects yourself (as
                        opposed to using the thread pool, which is shared for all apps on the
                        machine), you typically don't run into problems.

                        Also, just for your knowelege, the bool property on the
                        WaitOne()/WaitAny()/WaitAll() methods of the WaitHandle indicates whether you
                        want to exit from a synchronization domain, which is different than the
                        manual synchronization you get using Monitor/Synlock/WaitHandles/Whatever.
                        Synchronization Domains are virtual spaces set up within the AppDomain that
                        allow for coarse grained locking. To use it you must have an object that is
                        derived from ContextBoundObj ect, and then use the Synchronization Attribute to
                        tell the Framework how to set up the Synchronization domain. Any call coming
                        into a Synchronization domain from outside will effectvly be wrapped in a
                        Synlock block by the framework. It can be easier to manage (assuming you are
                        okay with having access to objects or object graphs synchronized), but most
                        folks aren't confortable with the overhead of using a ContextBoundObj ect.

                        So now that I've filled my useless knowlege quota for the day.....

                        I'm glad you've got a solution working...Good luck

                        Casey

                        "Perecli Manole" wrote:
                        [color=blue]
                        > I figured out a solution that is surprisingly simple.
                        > Apparently if you do a Thread.Sleep(0) , at the beginning of each thread 2 or
                        > 3 iteration (before the first SyncLock on those threads), the framework
                        > assumes for a brief period that there are no more tasks to follow and gives
                        > a time slice back to the waiting thread that was pulsed, rather than taking
                        > on another lock request from thread 2 or 3.
                        >
                        > The Sleep() seems to behave similar to DoEvents() in the UI context.
                        > With this approach I can keep using the Monitor.Wait/Pulse which buys me the
                        > context unlocking.
                        >
                        > Thank you for all your help. It definitely got ideas steering in my head by
                        > understanding what is really happening.
                        >
                        > Perry
                        >
                        >
                        > "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                        > news:07254588-1E21-4711-954D-F9C7DFDB4859@mi crosoft.com...[color=green]
                        > >I think the problem is that you are calling the Wait() mehod on your wait
                        > > handle within your SynLock block. The one thing Monitor.Wait does that
                        > > you
                        > > don't get with WaitHandles is that it releases the Lock on the Object you
                        > > call Wait on.
                        > >
                        > > I would say break it out into two SynLock groups in Thread 1, one locking
                        > > the resources just prior to calling WaitHandle.Wait (), and the other after
                        > > the Wait returns.
                        > >
                        > > You'll need to limit the scope of the SynLock in Thread's 2 & 3 as well.
                        > >
                        > > I'm afraid, though, that you may run into a similar problem as the one you
                        > > were experiencing with the Monitor object. You may want to consider using
                        > > the Semiphore class to allow 2 classes to access your _objTxRxSync object
                        > > at
                        > > a time. You would probably also need to use either a WaitHandle, or a
                        > > global
                        > > (and locked) variable to make sure that Threads 2 & 3 don't do their thing
                        > > until Thread 1 is ready. Adding the Semiphore will give you the ability
                        > > to
                        > > make sure only two threads will be working with the resources at a time,
                        > > though.
                        > >
                        > > Does this make any sense?
                        > >
                        > > Casey
                        > >
                        > > "Perecli Manole" wrote:
                        > >[color=darkred]
                        > >> I had the same thought as you so I tried the AutoResetEvent. This
                        > >> approach
                        > >> has a strange side effect though. The WaitHandle, I'am guessing, seems to
                        > >> prevent the SerialPort.Data Received event from fireing so thread 2 and
                        > >> above
                        > >> are not being called causing the WaitOne to always expire on the timout.
                        > >> When using the Monitor.Wait function instead the event is raised again.
                        > >> Can
                        > >> this be explained? Here a snipit that shows the basics:
                        > >>
                        > >> 'global
                        > >> Private _ARE1 As New AutoResetEvent( False)
                        > >> Private _ARE2 As New AutoResetEvent( False)
                        > >>
                        > >> '---------------------- transmit tread 1 ----------------------
                        > >> SyncLock _objTxRxSync
                        > >> _objSerialPort. Write(objTxPack et.Bytes, 0,
                        > >> objCurrTxPacket .Bytes.Length)
                        > >> _objTxRxSync.As sertedPacket = objTxPacket
                        > >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                        > >> If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                        > >> If objTxPacket.Nee dsPacketRespons e Then
                        > >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                        > >> _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                        > >> End If
                        > >> End If
                        > >> End SyncLock
                        > >>
                        > >> '------------------receive threads 2,3,n.... ---------------------
                        > >> SyncLock _objTxRxSync
                        > >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                        > >> _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                        > >> RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                        > >> _ARE1.Set()
                        > >> Exit Sub
                        > >> End If
                        > >> End SyncLock
                        > >>
                        > >> 'do some work that does not need syncronization for non echo packets only
                        > >> '..............
                        > >>
                        > >> SyncLock _objTxRxSync
                        > >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                        > >> _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                        > >> _ARE2.Set()
                        > >> End If
                        > >> End SyncLock
                        > >>
                        > >> RaiseCallBackEv ent(objRxPacket )
                        > >>
                        > >>
                        > >>
                        > >> Thanks
                        > >> Perry
                        > >>
                        > >>
                        > >>
                        > >>
                        > >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                        > >> news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...
                        > >> > Well, my first suggestion might be to utilize a WaitHandle derived
                        > >> > object
                        > >> > (Either a ManualResetEven t or AutoResetEvent most likely). WaitHandles
                        > >> > provide similar signalling to what is available with the Monitor class,
                        > >> > but
                        > >> > the fact that you can manually reset an event means that other threads
                        > >> > which
                        > >> > may call Wait on the handle will not block on that call until the
                        > >> > handle
                        > >> > is
                        > >> > reset.
                        > >> >
                        > >> > For your description, it sounds like you may want to consider creating
                        > >> > two
                        > >> > WaitHandle objects, one for Thread2 and one for Thread3, then in
                        > >> > Thread1
                        > >> > call
                        > >> > the static WaitHandle.Wait Any() passing in an array with both of those
                        > >> > objects. Once Thread2 or Thread3 signals thier handle (using Set())
                        > >> > then
                        > >> > Thread1 will pick back up.
                        > >> >
                        > >> > WaitHandle includes WaitOne, which waits for a single WaitHandle object
                        > >> > to
                        > >> > be signaled, WaitAny, which waits for any in an array of WaitHandles to
                        > >> > be
                        > >> > signaled, and WaitAll, which waits for all WaitHandles in an array to
                        > >> > be
                        > >> > signaled. The instances include the Set/Reset methods, but also have a
                        > >> > SignalAndWait method, which allows you to signal one WaitHandle, and
                        > >> > Wait
                        > >> > on
                        > >> > another (as a single operation). It seems like some experimenting with
                        > >> > these
                        > >> > might give you the some decent results.
                        > >> >
                        > >> > Looking at your original post again, it looks like this example from
                        > >> > Juval
                        > >> > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He calls
                        > >> > this a
                        > >> > "Rendezvous Helper", and describes it as a way to allow two threads to
                        > >> > do
                        > >> > work independently, and then wait for one another to to complete before
                        > >> > moving on... For what it is worth here is the code (hope C# is okay):
                        > >> >
                        > >> > public class Rendezvous
                        > >> > {
                        > >> > AutoResetEvent m_First = new AutoResetEvent( true);
                        > >> > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                        > >> > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                        > >> >
                        > >> > public void Wait( )
                        > >> > {
                        > >> > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                        > >> > if(first)
                        > >> > {
                        > >> > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                        > >> > }
                        > >> > else
                        > >> > {
                        > >> > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                        > >> > }
                        > >> > }
                        > >> > public void Reset( )
                        > >> > {
                        > >> > m_First.Set( );
                        > >> > }
                        > >> > }
                        > >> >
                        > >> > Here's a usage sample:
                        > >> >
                        > >> > public class RendezvousDemo
                        > >> > {
                        > >> > Rendezvous m_Rendezvous = new Rendezvous( );
                        > >> >
                        > >> > public void ThreadMethod1( )
                        > >> > {
                        > >> > //Do some work, then
                        > >> > m_Rendezvous.Wa it( );
                        > >> > //Continue executing
                        > >> > }
                        > >> > public void ThreadMethod2( )
                        > >> > {
                        > >> > //Do some work, then
                        > >> > m_Rendezvous.Wa it( );
                        > >> > //Continue executing
                        > >> >
                        > >> > }
                        > >> > }
                        > >> > RendezvousDemo demo = new RendezvousDemo( );
                        > >> > Thread thread1 = new Thread(demo.Thr eadMethod1);
                        > >> > thread1.Start( );
                        > >> >
                        > >> > Thread thread2 = new Thread(demo.Thr eadMethod2);
                        > >> > thread2.Start( );
                        > >> >
                        > >> > Basically what this boils down to is that thread1 and thread2 are
                        > >> > started,
                        > >> > and whichever one finishes first is blocked until the other is
                        > >> > finished,
                        > >> > at
                        > >> > which point they both continue.
                        > >> >
                        > >> > I'm not sure if the example is too abstract for your needs, but
                        > >> > hopefully
                        > >> > it
                        > >> > gives you enough to tinker with.
                        > >> >
                        > >> > "Perecli Manole" wrote:
                        > >> >
                        > >> >> Thank you for the detail description, that explains the unpredictable
                        > >> >> behavior I am experiencing.
                        > >> >>
                        > >> >> But, in order for my application to work properly, I absolutely need
                        > >> >> the
                        > >> >> waiting thread (Thread 1) to be the next thread that aquires the lock
                        > >> >> after
                        > >> >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after every
                        > >> >> and
                        > >> >> any pulse from any other thread. How can I achieve this even if it has
                        > >> >> to
                        > >> >> be
                        > >> >> done with a different mechanism?
                        > >> >>
                        > >> >> Thanks
                        > >> >> Perry
                        > >> >>
                        > >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                        > >> >> message
                        > >> >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...
                        > >> >> > Okay, I think I understand more of your issue now. I'll see if I
                        > >> >> > can
                        > >> >> > explain
                        > >> >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll()
                        > >> >> > calls:
                        > >> >> >
                        > >> >> > Whenever you call Monitor.Wait(), the thread that makes the call
                        > >> >> > gets
                        > >> >> > put
                        > >> >> > into a Wait Queue, and releases the lock on the monitored object.
                        > >> >> > At
                        > >> >> > this
                        > >> >> > point another thread may acquire the lock, and even call Wait()
                        > >> >> > itself.
                        > >> >> > Once
                        > >> >> > a thread calls Pulse() on the Monitor, the first thread in the Wait
                        > >> >> > Queue
                        > >> >> > gets moved into the Lock Queue (if you use PulseAll() then all of
                        > >> >> > the
                        > >> >> > threads
                        > >> >> > in the Wait Queue get moved to the lock queue). Once the thread
                        > >> >> > that
                        > >> >> > called
                        > >> >> > Pulse() is done, the next item in the Lock Queue will get the lock.
                        > >> >> >
                        > >> >> > I think the problem your running into comes from the fact that
                        > >> >> > Thread 1
                        > >> >> > is
                        > >> >> > being put in the Lock Queue behind Thread 2 or Thread 3 (depending
                        > >> >> > on
                        > >> >> > which
                        > >> >> > got the lock on the object after Thread1 called Wait()).
                        > >> >> >
                        > >> >> > I think, to directly answer your question below, that after Thread 2
                        > >> >> > calls
                        > >> >> > Pulse, then Thread 3 will get the object next, followed by Thread 1.
                        > >> >> > At
                        > >> >> > least that is assuming the order of the threads is constant, which
                        > >> >> > you
                        > >> >> > can't
                        > >> >> > always rely on (see my original response).
                        > >> >> >
                        > >> >> > Does that make sense?
                        > >> >> >
                        > >> >> > "Perecli Manole" wrote:
                        > >> >> >
                        > >> >> >> Could you also answer the more important last question I posed in
                        > >> >> >> my
                        > >> >> >> last
                        > >> >> >> post?
                        > >> >> >>
                        > >> >> >> "And if thread 2 gets the resource and then releases it with a
                        > >> >> >> Monitor.Pulse, will thread 3 then get the resource or will thread 1
                        > >> >> >> get
                        > >> >> >> it
                        > >> >> >> first?"
                        > >> >> >>
                        > >> >> >> Thanks
                        > >> >> >> Perry
                        > >> >> >>
                        > >> >> >>[/color][/color][/color]

                        Comment

                        • Perecli Manole

                          #13
                          Re: threading - Monitor.Wait/Pulse

                          Thanks again for the great insights.

                          Perry

                          "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                          news:CD527377-9708-4F7C-BD6E-A696B1273D0B@mi crosoft.com...[color=blue]
                          > That is true....The Sleep() call basically tells the OS that the thread is
                          > done with it's time slot for now. I can say that officially, using Sleep
                          > for
                          > thread synchronization is considered a "Bad Thing" since there is no way
                          > to
                          > know for sure that the threads are getting started in a particular
                          > order....In reality, though, if your creating the thread objects yourself
                          > (as
                          > opposed to using the thread pool, which is shared for all apps on the
                          > machine), you typically don't run into problems.
                          >
                          > Also, just for your knowelege, the bool property on the
                          > WaitOne()/WaitAny()/WaitAll() methods of the WaitHandle indicates whether
                          > you
                          > want to exit from a synchronization domain, which is different than the
                          > manual synchronization you get using Monitor/Synlock/WaitHandles/Whatever.
                          > Synchronization Domains are virtual spaces set up within the AppDomain
                          > that
                          > allow for coarse grained locking. To use it you must have an object that
                          > is
                          > derived from ContextBoundObj ect, and then use the Synchronization Attribute
                          > to
                          > tell the Framework how to set up the Synchronization domain. Any call
                          > coming
                          > into a Synchronization domain from outside will effectvly be wrapped in a
                          > Synlock block by the framework. It can be easier to manage (assuming you
                          > are
                          > okay with having access to objects or object graphs synchronized), but
                          > most
                          > folks aren't confortable with the overhead of using a ContextBoundObj ect.
                          >
                          > So now that I've filled my useless knowlege quota for the day.....
                          >
                          > I'm glad you've got a solution working...Good luck
                          >
                          > Casey
                          >
                          > "Perecli Manole" wrote:
                          >[color=green]
                          >> I figured out a solution that is surprisingly simple.
                          >> Apparently if you do a Thread.Sleep(0) , at the beginning of each thread 2
                          >> or
                          >> 3 iteration (before the first SyncLock on those threads), the framework
                          >> assumes for a brief period that there are no more tasks to follow and
                          >> gives
                          >> a time slice back to the waiting thread that was pulsed, rather than
                          >> taking
                          >> on another lock request from thread 2 or 3.
                          >>
                          >> The Sleep() seems to behave similar to DoEvents() in the UI context.
                          >> With this approach I can keep using the Monitor.Wait/Pulse which buys me
                          >> the
                          >> context unlocking.
                          >>
                          >> Thank you for all your help. It definitely got ideas steering in my head
                          >> by
                          >> understanding what is really happening.
                          >>
                          >> Perry
                          >>
                          >>
                          >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in message
                          >> news:07254588-1E21-4711-954D-F9C7DFDB4859@mi crosoft.com...[color=darkred]
                          >> >I think the problem is that you are calling the Wait() mehod on your
                          >> >wait
                          >> > handle within your SynLock block. The one thing Monitor.Wait does that
                          >> > you
                          >> > don't get with WaitHandles is that it releases the Lock on the Object
                          >> > you
                          >> > call Wait on.
                          >> >
                          >> > I would say break it out into two SynLock groups in Thread 1, one
                          >> > locking
                          >> > the resources just prior to calling WaitHandle.Wait (), and the other
                          >> > after
                          >> > the Wait returns.
                          >> >
                          >> > You'll need to limit the scope of the SynLock in Thread's 2 & 3 as
                          >> > well.
                          >> >
                          >> > I'm afraid, though, that you may run into a similar problem as the one
                          >> > you
                          >> > were experiencing with the Monitor object. You may want to consider
                          >> > using
                          >> > the Semiphore class to allow 2 classes to access your _objTxRxSync
                          >> > object
                          >> > at
                          >> > a time. You would probably also need to use either a WaitHandle, or a
                          >> > global
                          >> > (and locked) variable to make sure that Threads 2 & 3 don't do their
                          >> > thing
                          >> > until Thread 1 is ready. Adding the Semiphore will give you the
                          >> > ability
                          >> > to
                          >> > make sure only two threads will be working with the resources at a
                          >> > time,
                          >> > though.
                          >> >
                          >> > Does this make any sense?
                          >> >
                          >> > Casey
                          >> >
                          >> > "Perecli Manole" wrote:
                          >> >
                          >> >> I had the same thought as you so I tried the AutoResetEvent. This
                          >> >> approach
                          >> >> has a strange side effect though. The WaitHandle, I'am guessing, seems
                          >> >> to
                          >> >> prevent the SerialPort.Data Received event from fireing so thread 2 and
                          >> >> above
                          >> >> are not being called causing the WaitOne to always expire on the
                          >> >> timout.
                          >> >> When using the Monitor.Wait function instead the event is raised
                          >> >> again.
                          >> >> Can
                          >> >> this be explained? Here a snipit that shows the basics:
                          >> >>
                          >> >> 'global
                          >> >> Private _ARE1 As New AutoResetEvent( False)
                          >> >> Private _ARE2 As New AutoResetEvent( False)
                          >> >>
                          >> >> '---------------------- transmit tread 1 ----------------------
                          >> >> SyncLock _objTxRxSync
                          >> >> _objSerialPort. Write(objTxPack et.Bytes, 0,
                          >> >> objCurrTxPacket .Bytes.Length)
                          >> >> _objTxRxSync.As sertedPacket = objTxPacket
                          >> >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo
                          >> >> If _ARE1.WaitOne(P ACKET_ECHO_TIME OUT, True) Then
                          >> >> If objTxPacket.Nee dsPacketRespons e Then
                          >> >> _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response
                          >> >> _ARE2.WaitOne(P ACKET_RESPONSE_ TIMEOUT, True)
                          >> >> End If
                          >> >> End If
                          >> >> End SyncLock
                          >> >>
                          >> >> '------------------receive threads 2,3,n.... ---------------------
                          >> >> SyncLock _objTxRxSync
                          >> >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Echo AndAlso
                          >> >> _objTxRxSync.As sertedPacket.Eq uals(_objRxPack et) Then
                          >> >> RaiseCallBackEv ent(_objTxRxSyn c.AssertedPacke t)
                          >> >> _ARE1.Set()
                          >> >> Exit Sub
                          >> >> End If
                          >> >> End SyncLock
                          >> >>
                          >> >> 'do some work that does not need syncronization for non echo packets
                          >> >> only
                          >> >> '..............
                          >> >>
                          >> >> SyncLock _objTxRxSync
                          >> >> If _objTxRxSync.Ma tchNeeded = TxRxSync.MatchT ype.Response AndAlso
                          >> >> _objTxRxSync.As sertedPacket.Va lidPacketRespon se(objRxPacket) Then
                          >> >> _ARE2.Set()
                          >> >> End If
                          >> >> End SyncLock
                          >> >>
                          >> >> RaiseCallBackEv ent(objRxPacket )
                          >> >>
                          >> >>
                          >> >>
                          >> >> Thanks
                          >> >> Perry
                          >> >>
                          >> >>
                          >> >>
                          >> >>
                          >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                          >> >> message
                          >> >> news:106CF2E8-385E-4B70-8FEE-445A4B855F6B@mi crosoft.com...
                          >> >> > Well, my first suggestion might be to utilize a WaitHandle derived
                          >> >> > object
                          >> >> > (Either a ManualResetEven t or AutoResetEvent most likely).
                          >> >> > WaitHandles
                          >> >> > provide similar signalling to what is available with the Monitor
                          >> >> > class,
                          >> >> > but
                          >> >> > the fact that you can manually reset an event means that other
                          >> >> > threads
                          >> >> > which
                          >> >> > may call Wait on the handle will not block on that call until the
                          >> >> > handle
                          >> >> > is
                          >> >> > reset.
                          >> >> >
                          >> >> > For your description, it sounds like you may want to consider
                          >> >> > creating
                          >> >> > two
                          >> >> > WaitHandle objects, one for Thread2 and one for Thread3, then in
                          >> >> > Thread1
                          >> >> > call
                          >> >> > the static WaitHandle.Wait Any() passing in an array with both of
                          >> >> > those
                          >> >> > objects. Once Thread2 or Thread3 signals thier handle (using Set())
                          >> >> > then
                          >> >> > Thread1 will pick back up.
                          >> >> >
                          >> >> > WaitHandle includes WaitOne, which waits for a single WaitHandle
                          >> >> > object
                          >> >> > to
                          >> >> > be signaled, WaitAny, which waits for any in an array of WaitHandles
                          >> >> > to
                          >> >> > be
                          >> >> > signaled, and WaitAll, which waits for all WaitHandles in an array
                          >> >> > to
                          >> >> > be
                          >> >> > signaled. The instances include the Set/Reset methods, but also
                          >> >> > have a
                          >> >> > SignalAndWait method, which allows you to signal one WaitHandle, and
                          >> >> > Wait
                          >> >> > on
                          >> >> > another (as a single operation). It seems like some experimenting
                          >> >> > with
                          >> >> > these
                          >> >> > might give you the some decent results.
                          >> >> >
                          >> >> > Looking at your original post again, it looks like this example from
                          >> >> > Juval
                          >> >> > Lowy's "Programmin g .Net Components" 2nd ed. may be helpful. He
                          >> >> > calls
                          >> >> > this a
                          >> >> > "Rendezvous Helper", and describes it as a way to allow two threads
                          >> >> > to
                          >> >> > do
                          >> >> > work independently, and then wait for one another to to complete
                          >> >> > before
                          >> >> > moving on... For what it is worth here is the code (hope C# is
                          >> >> > okay):
                          >> >> >
                          >> >> > public class Rendezvous
                          >> >> > {
                          >> >> > AutoResetEvent m_First = new AutoResetEvent( true);
                          >> >> > AutoResetEvent m_Event1 = new AutoResetEvent( false);
                          >> >> > AutoResetEvent m_Event2 = new AutoResetEvent( false);
                          >> >> >
                          >> >> > public void Wait( )
                          >> >> > {
                          >> >> > bool first = m_First.WaitOne (TimeSpan.Zero, false);
                          >> >> > if(first)
                          >> >> > {
                          >> >> > WaitHandle.Sign alAndWait(m_Eve nt1,m_Event2);
                          >> >> > }
                          >> >> > else
                          >> >> > {
                          >> >> > WaitHandle.Sign alAndWait(m_Eve nt2,m_Event1);
                          >> >> > }
                          >> >> > }
                          >> >> > public void Reset( )
                          >> >> > {
                          >> >> > m_First.Set( );
                          >> >> > }
                          >> >> > }
                          >> >> >
                          >> >> > Here's a usage sample:
                          >> >> >
                          >> >> > public class RendezvousDemo
                          >> >> > {
                          >> >> > Rendezvous m_Rendezvous = new Rendezvous( );
                          >> >> >
                          >> >> > public void ThreadMethod1( )
                          >> >> > {
                          >> >> > //Do some work, then
                          >> >> > m_Rendezvous.Wa it( );
                          >> >> > //Continue executing
                          >> >> > }
                          >> >> > public void ThreadMethod2( )
                          >> >> > {
                          >> >> > //Do some work, then
                          >> >> > m_Rendezvous.Wa it( );
                          >> >> > //Continue executing
                          >> >> >
                          >> >> > }
                          >> >> > }
                          >> >> > RendezvousDemo demo = new RendezvousDemo( );
                          >> >> > Thread thread1 = new Thread(demo.Thr eadMethod1);
                          >> >> > thread1.Start( );
                          >> >> >
                          >> >> > Thread thread2 = new Thread(demo.Thr eadMethod2);
                          >> >> > thread2.Start( );
                          >> >> >
                          >> >> > Basically what this boils down to is that thread1 and thread2 are
                          >> >> > started,
                          >> >> > and whichever one finishes first is blocked until the other is
                          >> >> > finished,
                          >> >> > at
                          >> >> > which point they both continue.
                          >> >> >
                          >> >> > I'm not sure if the example is too abstract for your needs, but
                          >> >> > hopefully
                          >> >> > it
                          >> >> > gives you enough to tinker with.
                          >> >> >
                          >> >> > "Perecli Manole" wrote:
                          >> >> >
                          >> >> >> Thank you for the detail description, that explains the
                          >> >> >> unpredictable
                          >> >> >> behavior I am experiencing.
                          >> >> >>
                          >> >> >> But, in order for my application to work properly, I absolutely
                          >> >> >> need
                          >> >> >> the
                          >> >> >> waiting thread (Thread 1) to be the next thread that aquires the
                          >> >> >> lock
                          >> >> >> after
                          >> >> >> either Thread 2 or 3 pulse. Thread 1 MUST be checked with after
                          >> >> >> every
                          >> >> >> and
                          >> >> >> any pulse from any other thread. How can I achieve this even if it
                          >> >> >> has
                          >> >> >> to
                          >> >> >> be
                          >> >> >> done with a different mechanism?
                          >> >> >>
                          >> >> >> Thanks
                          >> >> >> Perry
                          >> >> >>
                          >> >> >> "Casey Kramer" <CaseyKramer@di scussions.micro soft.com> wrote in
                          >> >> >> message
                          >> >> >> news:FF8949ED-C2D3-4281-944E-DE31FE76BBF0@mi crosoft.com...
                          >> >> >> > Okay, I think I understand more of your issue now. I'll see if I
                          >> >> >> > can
                          >> >> >> > explain
                          >> >> >> > generally how Monitor Deals with Wait() and Pulse()/PulseAll()
                          >> >> >> > calls:
                          >> >> >> >
                          >> >> >> > Whenever you call Monitor.Wait(), the thread that makes the call
                          >> >> >> > gets
                          >> >> >> > put
                          >> >> >> > into a Wait Queue, and releases the lock on the monitored object.
                          >> >> >> > At
                          >> >> >> > this
                          >> >> >> > point another thread may acquire the lock, and even call Wait()
                          >> >> >> > itself.
                          >> >> >> > Once
                          >> >> >> > a thread calls Pulse() on the Monitor, the first thread in the
                          >> >> >> > Wait
                          >> >> >> > Queue
                          >> >> >> > gets moved into the Lock Queue (if you use PulseAll() then all of
                          >> >> >> > the
                          >> >> >> > threads
                          >> >> >> > in the Wait Queue get moved to the lock queue). Once the thread
                          >> >> >> > that
                          >> >> >> > called
                          >> >> >> > Pulse() is done, the next item in the Lock Queue will get the
                          >> >> >> > lock.
                          >> >> >> >
                          >> >> >> > I think the problem your running into comes from the fact that
                          >> >> >> > Thread 1
                          >> >> >> > is
                          >> >> >> > being put in the Lock Queue behind Thread 2 or Thread 3
                          >> >> >> > (depending
                          >> >> >> > on
                          >> >> >> > which
                          >> >> >> > got the lock on the object after Thread1 called Wait()).
                          >> >> >> >
                          >> >> >> > I think, to directly answer your question below, that after
                          >> >> >> > Thread 2
                          >> >> >> > calls
                          >> >> >> > Pulse, then Thread 3 will get the object next, followed by Thread
                          >> >> >> > 1.
                          >> >> >> > At
                          >> >> >> > least that is assuming the order of the threads is constant,
                          >> >> >> > which
                          >> >> >> > you
                          >> >> >> > can't
                          >> >> >> > always rely on (see my original response).
                          >> >> >> >
                          >> >> >> > Does that make sense?
                          >> >> >> >
                          >> >> >> > "Perecli Manole" wrote:
                          >> >> >> >
                          >> >> >> >> Could you also answer the more important last question I posed
                          >> >> >> >> in
                          >> >> >> >> my
                          >> >> >> >> last
                          >> >> >> >> post?
                          >> >> >> >>
                          >> >> >> >> "And if thread 2 gets the resource and then releases it with a
                          >> >> >> >> Monitor.Pulse, will thread 3 then get the resource or will
                          >> >> >> >> thread 1
                          >> >> >> >> get
                          >> >> >> >> it
                          >> >> >> >> first?"
                          >> >> >> >>
                          >> >> >> >> Thanks
                          >> >> >> >> Perry
                          >> >> >> >>
                          >> >> >> >>[/color][/color][/color]


                          Comment

                          Working...