Using delegates between main/sub threads

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Pixel.to.life

    Using delegates between main/sub threads

    Dear All,

    Here is a problem I am facing (it might be too simple, but then I
    admit I am not a Guru:-)

    I have a main thread, in managed C++, that deals with displaying a
    form and some controls.

    I invoke another thread for some processing from this thread, so
    basically the main thread is waiting on the sub thread.

    Now the sub-thread has to keep posting its progress to the main
    thread. I have a delegate mechanism for that. So using mutex, I update
    the progress variable in the sub-thread's scope, and then invoke the
    main thread's delegate method to display the progress.

    The problem is just when the delegate is invoked. Control switches
    form sub to main thread. But main thread is already waiting for the
    sub thread to finish, so it deadlocks right there.

    Any ideas/suggestions? The solution seems simple, just that I dont get
    it yet.

    Thanks!
  • Jon Skeet [C# MVP]

    #2
    Re: Using delegates between main/sub threads

    Pixel.to.life <pixel.to.life@ gmail.comwrote:
    Here is a problem I am facing (it might be too simple, but then I
    admit I am not a Guru:-)
    >
    I have a main thread, in managed C++, that deals with displaying a
    form and some controls.
    >
    I invoke another thread for some processing from this thread, so
    basically the main thread is waiting on the sub thread.
    That's your problem - don't make the main thread wait. The point of
    using other threads to do work in a UI application is to avoid the UI
    locking up. You need to keep the UI event loop free to handle things
    like screen refreshes.

    --
    Jon Skeet - <skeet@pobox.co m>
    Web site: http://www.pobox.com/~skeet
    Blog: http://www.msmvps.com/jon.skeet
    C# in Depth: http://csharpindepth.com

    Comment

    • Pixel.to.life

      #3
      Re: Using delegates between main/sub threads

      On May 6, 1:21 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
      Pixel.to.life <pixel.to.l...@ gmail.comwrote:
      Here is a problem I am facing (it might be too simple, but then I
      admit I am not a Guru:-)
      >
      I have a main thread, in managed C++, that deals with displaying a
      form and some controls.
      >
      I invoke another thread for some processing from this thread, so
      basically the main thread is waiting on the sub thread.
      >
      That's your problem - don't make the main thread wait. The point of
      using other threads to do work in a UI application is to avoid the UI
      locking up. You need to keep the UI event loop free to handle things
      like screen refreshes.
      >
      --
      Jon Skeet - <sk...@pobox.co m>
      Web site:http://www.pobox.com/~skeet 
      Blog:http://www.msmvps.com/jon.skeet
      C# in Depth:http://csharpindepth.com
      Thanks Jon.

      I realised it after I posted.

      Fow now I use WaitForSingleTh read(..) API to wait on the sub thread.
      Whats the alternative so the sub thread processing can be done
      asynchronously?

      I am looking at MsgWaitForMulti pleObjects(..) instead to see if I can
      get status right there.

      Sorry I am a novice to multithreading with GUI.

      Comment

      • Pixel.to.life

        #4
        Re: Using delegates between main/sub threads

        On May 6, 1:21 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
        Pixel.to.life <pixel.to.l...@ gmail.comwrote:
        Here is a problem I am facing (it might be too simple, but then I
        admit I am not a Guru:-)
        >
        I have a main thread, in managed C++, that deals with displaying a
        form and some controls.
        >
        I invoke another thread for some processing from this thread, so
        basically the main thread is waiting on the sub thread.
        >
        That's your problem - don't make the main thread wait. The point of
        using other threads to do work in a UI application is to avoid the UI
        locking up. You need to keep the UI event loop free to handle things
        like screen refreshes.
        >
        --
        Jon Skeet - <sk...@pobox.co m>
        Web site:http://www.pobox.com/~skeet 
        Blog:http://www.msmvps.com/jon.skeet
        C# in Depth:http://csharpindepth.com
        Also, I need to wait for the sub thread because the main thread has to
        do some consilidation once the sub thread is done. If I remove the
        WaitForSingleTh read(...) call, how do I know the subthread is done?

        Thanks.

        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: Using delegates between main/sub threads

          Pixel.to.life <pixel.to.life@ gmail.comwrote:
          Also, I need to wait for the sub thread because the main thread has to
          do some consilidation once the sub thread is done. If I remove the
          WaitForSingleTh read(...) call, how do I know the subthread is done?
          Get the subthread to post back into the main thread, just as it would
          to update the UI - using Control.Invoke or Control.BeginIn voke.

          --
          Jon Skeet - <skeet@pobox.co m>
          Web site: http://www.pobox.com/~skeet
          Blog: http://www.msmvps.com/jon.skeet
          C# in Depth: http://csharpindepth.com

          Comment

          • Jon Skeet [C# MVP]

            #6
            Re: Using delegates between main/sub threads

            Pixel.to.life <pixel.to.life@ gmail.comwrote:
            Fow now I use WaitForSingleTh read(..) API to wait on the sub thread.
            Whats the alternative so the sub thread processing can be done
            asynchronously?
            Just don't wait at all :) If you need to do something when the other
            thread's finished, get it to tell you with a call to
            Control.Invoke/BeginInvoke.
            I am looking at MsgWaitForMulti pleObjects(..) instead to see if I can
            get status right there.
            >
            Sorry I am a novice to multithreading with GUI.
            That's okay - it's a tricky topic. I have a brief introduction to
            threading here:

            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.


            --
            Jon Skeet - <skeet@pobox.co m>
            Web site: http://www.pobox.com/~skeet
            Blog: http://www.msmvps.com/jon.skeet
            C# in Depth: http://csharpindepth.com

            Comment

            • Pixel.to.life

              #7
              Re: Using delegates between main/sub threads

              On May 6, 3:15 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
              Pixel.to.life <pixel.to.l...@ gmail.comwrote:
              Fow now I use WaitForSingleTh read(..) API to wait on the sub thread.
              Whats the alternative so the sub thread processing can be done
              asynchronously?
              >
              Just don't wait at all :) If you need to do something when the other
              thread's finished, get it to tell you with a call to
              Control.Invoke/BeginInvoke.
              >
              I am looking at MsgWaitForMulti pleObjects(..) instead to see if I can
              get status right there.
              >
              Sorry I am a novice to multithreading with GUI.
              >
              That's okay - it's a tricky topic. I have a brief introduction to
              threading here:
              >
              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

              >
              --
              Jon Skeet - <sk...@pobox.co m>
              Web site:http://www.pobox.com/~skeet 
              Blog:http://www.msmvps.com/jon.skeet
              C# in Depth:http://csharpindepth.com

              Thanks a lot, Jon. I finally figured out how to do it. I dont wait,
              but let the sub thread work async-ly.. and have it post a message
              BeginInvoke() when its done.

              I noticed that BeginInvoke() isnt as powerful in having UI refresh its
              controls.. and when I use Invoke(), its the same problem as before.
              Its blocking kind of.

              Thanks again!

              Comment

              • Jon Skeet [C# MVP]

                #8
                Re: Using delegates between main/sub threads

                Pixel.to.life <pixel.to.life@ gmail.comwrote:

                <snip>
                I noticed that BeginInvoke() isnt as powerful in having UI refresh its
                controls..
                What exactly do you mean?
                and when I use Invoke(), its the same problem as before.
                Its blocking kind of.
                No "kind of" about it - it blocks until the delegate has executed in
                the UI thread.

                --
                Jon Skeet - <skeet@pobox.co m>
                Web site: http://www.pobox.com/~skeet
                Blog: http://www.msmvps.com/jon.skeet
                C# in Depth: http://csharpindepth.com

                Comment

                • Pixel.to.life

                  #9
                  Re: Using delegates between main/sub threads

                  On May 7, 1:46 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
                  Pixel.to.life <pixel.to.l...@ gmail.comwrote:
                  >
                  <snip>
                  >
                  I noticed that BeginInvoke() isnt as powerful in having UI refresh its
                  controls..
                  >
                  What exactly do you mean?
                  >
                  and when I use Invoke(), its the same problem as before.
                  Its blocking kind of.
                  >
                  No "kind of" about it - it blocks until the delegate has executed in
                  the UI thread.
                  >
                  --
                  Jon Skeet - <sk...@pobox.co m>
                  Web site:http://www.pobox.com/~skeet 
                  Blog:http://www.msmvps.com/jon.skeet
                  C# in Depth:http://csharpindepth.com

                  Ok I correct myself: Invoke() is blocking exactly until the UI updates
                  itself.

                  Comment

                  • Jon Skeet [C# MVP]

                    #10
                    Re: Using delegates between main/sub threads

                    Pixel.to.life <pixel.to.life@ gmail.comwrote:
                    Ok I correct myself: Invoke() is blocking exactly until the UI updates
                    itself.
                    I should just apologise for the tone of my previous message - it wasn't
                    *meant* to sound patronising or impatient, but I suspect it came out
                    that way. Amazingly enough, I couldn't find the blocking nature on the
                    Control.Invoke documentation page. It's probably there somewhere,
                    but...

                    --
                    Jon Skeet - <skeet@pobox.co m>
                    Web site: http://www.pobox.com/~skeet
                    Blog: http://www.msmvps.com/jon.skeet
                    C# in Depth: http://csharpindepth.com

                    Comment

                    • Peter Duniho

                      #11
                      Re: Using delegates between main/sub threads

                      On Wed, 07 May 2008 22:17:41 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
                      wrote:
                      Pixel.to.life <pixel.to.life@ gmail.comwrote:
                      >Ok I correct myself: Invoke() is blocking exactly until the UI updates
                      >itself.
                      Minor nit-pick: Invoke() only blocks "until the UI updates itself" if the
                      delegate being invoked updates the UI. For example, calling Refresh() or
                      Update().

                      In most cases, this isn't actually going to be the case. Neither of those
                      methods, for example, are generally found in well-written applications,
                      not being necessary. Typically, the invoked method will change some state
                      represented by the UI, but the act of actually redrawing that new state
                      visually will happen later. It's entirely possible for Invoke() to return
                      to the caller before the UI has updated itself.

                      The blocking behavior of Invoke() is defined to be that it blocks until
                      the delegate being invoked returns. No blocking longer than that is
                      guaranteed.
                      I should just apologise for the tone of my previous message - it wasn't
                      *meant* to sound patronising or impatient, but I suspect it came out
                      that way. Amazingly enough, I couldn't find the blocking nature on the
                      Control.Invoke documentation page. It's probably there somewhere,
                      but...
                      It seems to me that it's asynchronous operations that would warrant
                      calling out the specific nature of a method in the docs. IMHO, it's
                      reasonable to assume that a method is synchronous unless stated
                      otherwise. In that sense, the docs for Control.Invoke( ) have no need for
                      a specific statement that it's synchronous, blocking until the delegate is
                      done. It's implied, because it's always implied that a method won't
                      return until whatever that method does is done.

                      That said, if you're not happy with that implication, there is also the
                      same implication of synchronous behavior in the description of the return
                      value. The docs say that Control.Invoke( ) returns the return value from
                      the delegate being invoked. Since that return value can't possibly exist
                      until the delegate has itself returned, that's yet another reason that
                      it's implied in the docs that the delegate is invoked synchronously.

                      I don't think that there _is_ an explicit statement as to the
                      blocking/synchronous nature of Control.Invoke( ), but neither do I think
                      it's really necessary.

                      Pete

                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: Using delegates between main/sub threads

                        On May 8, 7:09 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
                        wrote:

                        <snip>
                        I don't think that there _is_ an explicit statement as to the
                        blocking/synchronous nature of Control.Invoke( ), but neither do I think
                        it's really necessary.
                        While I agree with your logic suggesting it's not *necessary*, I do
                        think it would be *useful* - particularly if it also pointed out the
                        option of using BeginInvoke() for a non-blocking form.

                        Will suggest it to the MSDN team when I have time...

                        Jon

                        Comment

                        • Ben Voigt [C++ MVP]

                          #13
                          Re: Using delegates between main/sub threads

                          It seems to me that it's asynchronous operations that would warrant
                          calling out the specific nature of a method in the docs. IMHO, it's
                          reasonable to assume that a method is synchronous unless stated
                          otherwise. In that sense, the docs for Control.Invoke( ) have no need
                          Rather, it's reasonable to assume that a method is executed on the same
                          thread unless stated otherwise. Synchronization comes with that behavior.
                          Once you take away the same thread assumption then synchronization should be
                          called out explicitly.
                          for a specific statement that it's synchronous, blocking until the
                          delegate is done. It's implied, because it's always implied that a
                          method won't return until whatever that method does is done.
                          You just pointed out that this frequently isn't the case (updating internal
                          UI state but the screen isn't updated until Windows sends a WM_PAINT).


                          Comment

                          • Peter Duniho

                            #14
                            Re: Using delegates between main/sub threads

                            On Fri, 09 May 2008 13:18:09 -0700, Ben Voigt [C++ MVP]
                            <rbv@nospam.nos pamwrote:
                            >It seems to me that it's asynchronous operations that would warrant
                            >calling out the specific nature of a method in the docs. IMHO, it's
                            >reasonable to assume that a method is synchronous unless stated
                            >otherwise. In that sense, the docs for Control.Invoke( ) have no need
                            >
                            Rather, it's reasonable to assume that a method is executed on the same
                            thread unless stated otherwise.
                            I only disagree with that statement inasmuch as you included the word
                            "rather". I don't see either assumption as mutually exclusive.
                            Synchronization comes with that behavior.
                            Executing on the same thread implies synchronization , yes. But the
                            converse -- that not executing on the same thread implies lack of
                            synchronization -- is not true. And so...
                            Once you take away the same thread assumption then synchronization
                            should be
                            called out explicitly.
                            I wouldn't invest any time or effort trying to convince someone to not add
                            such a statement to the docs. More detail is often useful. However, I
                            (obviously) disagree that there's a _need_. A benefit, yes. A need, no.
                            >for a specific statement that it's synchronous, blocking until the
                            >delegate is done. It's implied, because it's always implied that a
                            >method won't return until whatever that method does is done.
                            >
                            You just pointed out that this frequently isn't the case (updating
                            internal
                            UI state but the screen isn't updated until Windows sends a WM_PAINT).
                            I have no idea what you mean here. If you use Invoke() to call a method
                            that updates internal UI state, then when Invoke() returns, you can be
                            sure that what that method does -- updating internal UI state -- is done.
                            If the method doesn't send a WM_PAINT, then the question of when the
                            screen is updated or when a WM_PAINT message might be sent is irrelevant.
                            That's not what the method being invoked does.

                            Don't confuse what a method _does_ with what later implications that
                            activity might have. For example, the question of when a WM_PAINT message
                            is sent is independent of when a method that updates internal UI state is
                            done, and this is true whether you call that method directly within the
                            correct thread, or call it indirectly from another thread using Invoke().

                            Pete

                            Comment

                            • Ben Voigt [C++ MVP]

                              #15
                              Re: Using delegates between main/sub threads

                              I have no idea what you mean here. If you use Invoke() to call a
                              method that updates internal UI state, then when Invoke() returns,
                              you can be sure that what that method does -- updating internal UI
                              state -- is done. If the method doesn't send a WM_PAINT, then the
                              question of when the screen is updated or when a WM_PAINT message
                              might be sent is irrelevant. That's not what the method being invoked
                              does.
                              Don't confuse what a method _does_ with what later implications that
                              activity might have. For example, the question of when a WM_PAINT
                              message is sent is independent of when a method that updates internal
                              UI state is done, and this is true whether you call that method
                              directly within the correct thread, or call it indirectly from
                              another thread using Invoke().
                              But by this definition, BeginInvoke is also synchronous. It does not do
                              what the documentation says ("Executes a delegate asynchronously" ), it posts
                              a request into a queue corresponding to the UI thread, then returns. The
                              future execution of the delegate identified in that request is merely a
                              "later implication of that activity".
                              >
                              Pete

                              Comment

                              Working...