Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. WaitForSingleObject(m_SomeThread->m_hThread, INFINITE);

WaitForSingleObject(m_SomeThread->m_hThread, INFINITE);

Scheduled Pinned Locked Moved C / C++ / MFC
questionc++
21 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Lost User

    Here is what my instincts are telling me. 1.) You create your thread and it begins your small intensive calculation. 2.) Your parent thread is preempted and loses its CPU quantum slice before WaitForSingleObject is called. 3.) Your calculation is completed and the thread exits. 4.) Your parent thread resumes WaitForSingleObject and begins waiting on an invalid thread handle. I would suggest the following: 1.) Create your thread suspended. 2.) Duplicate the thread handle. 3.) Wait on the duplicated handle. 4.) Resume the thread. Let me know if it solves your problem. Best Wishes, -David Delaune

    R Offline
    R Offline
    Roger Stoltz
    wrote on last edited by
    #9

    Randor wrote:

    1.) Create your thread suspended. 2.) Duplicate the thread handle. 3.) Wait on the duplicated handle. 4.) Resume the thread.

    Better to create the thread suspended, set the CWinThread::m_bAutoDelete to FALSE and then resume the execution of the thread. The CWinThread object will normally destroy itself when the thread exits and consequently close the thread handle. This is prevented by setting m_bAutoDelete to FALSE. But it also means that the caller is responsible for deleting the CWinThread object when the thread has finished. As always: more info here[^].

    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
    "High speed never compensates for wrong direction!" - unknown

    L 1 Reply Last reply
    0
    • R Roger Stoltz

      Randor wrote:

      1.) Create your thread suspended. 2.) Duplicate the thread handle. 3.) Wait on the duplicated handle. 4.) Resume the thread.

      Better to create the thread suspended, set the CWinThread::m_bAutoDelete to FALSE and then resume the execution of the thread. The CWinThread object will normally destroy itself when the thread exits and consequently close the thread handle. This is prevented by setting m_bAutoDelete to FALSE. But it also means that the caller is responsible for deleting the CWinThread object when the thread has finished. As always: more info here[^].

      "It's supposed to be hard, otherwise anybody could do it!" - selfquote
      "High speed never compensates for wrong direction!" - unknown

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #10

      Hi Roger, Thanks for the comment. Yes what you have described is another valid method to avoid waiting on an invalid thread handle. Describing it as 'better' sounds like an opinion. Best Wishes, -David Delaune

      R 1 Reply Last reply
      0
      • L Lost User

        Hi Roger, Thanks for the comment. Yes what you have described is another valid method to avoid waiting on an invalid thread handle. Describing it as 'better' sounds like an opinion. Best Wishes, -David Delaune

        R Offline
        R Offline
        Roger Stoltz
        wrote on last edited by
        #11

        Hi David,

        Randor wrote:

        Describing it as 'better' sounds like an opinion.

        Mmmm, it may be so, but I'd like to clarify my opinion. ;-) If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED, so this cannot be the problem. If the handle is still valid ::WaitForSingleObject() will either return zero or wait as expected. Your suggestion to duplicate the handle is to circumvent the fact that CWinThread will close the handle in its destructor, unless the m_bAutoDelete member is set to FALSE. In this case my opinion of 'better' is to fix it the MFC way since it was introduced by MFC. I think it's cleaner and hence 'better', but whether that's 'better' or not is a matter of opinion. For what it's worth I think the OP has created some kind of race condition that may end up in a deadlock where the spawned thread sends a message to the main thread. In the message handler call chain he then waits for the thread to finished.....

        "It's supposed to be hard, otherwise anybody could do it!" - selfquote
        "High speed never compensates for wrong direction!" - unknown

        L 1 Reply Last reply
        0
        • R Roger Stoltz

          Hi David,

          Randor wrote:

          Describing it as 'better' sounds like an opinion.

          Mmmm, it may be so, but I'd like to clarify my opinion. ;-) If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED, so this cannot be the problem. If the handle is still valid ::WaitForSingleObject() will either return zero or wait as expected. Your suggestion to duplicate the handle is to circumvent the fact that CWinThread will close the handle in its destructor, unless the m_bAutoDelete member is set to FALSE. In this case my opinion of 'better' is to fix it the MFC way since it was introduced by MFC. I think it's cleaner and hence 'better', but whether that's 'better' or not is a matter of opinion. For what it's worth I think the OP has created some kind of race condition that may end up in a deadlock where the spawned thread sends a message to the main thread. In the message handler call chain he then waits for the thread to finished.....

          "It's supposed to be hard, otherwise anybody could do it!" - selfquote
          "High speed never compensates for wrong direction!" - unknown

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #12

          Roger Stoltz wrote:

          If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED

          This is not completely correct. The NT kernel recycles both window and thread identifiers (HANDLES). You can easily test this by creating a test dialog with 2 buttons. On the first button create a thread and on the second button end the thread. Rapidly press the buttons and observe the newly created thread sometimes has the same handle value in your traced output. It is the same for window handles... when they are closed the same value can be assigned to a window created in the near future. An excerpt from: The Birth of a Thread: CreateThread[^] Please do not make any assumptions about this identifier; all that is guaranteed is that while the thread is running, no other thread will ever have the same ID. The ID may be recycled later on after the thread has terminated. Multithreading for Rookies[^] Give Me a Handle, and I'll Show You an Object[^] 1.) The benefit of your option is the engineer does not need to call DuplicateHandle. On the negative side your option requires the engineer to manually perform the thread cleanup. 2.) The benefit of the other option is the engineer does no cleanup because m_bAutoDelete defaults to TRUE. On the negative side the engineer has to call DuplicateHandle and then CloseHandle when he is done waiting. Anyway, this debate is meanlingless. If the presented scenario is what is actually occuring then both options presented are good options. This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience. Best Wishes, -David Delaune

          R 1 Reply Last reply
          0
          • L Lost User

            Roger Stoltz wrote:

            If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED

            This is not completely correct. The NT kernel recycles both window and thread identifiers (HANDLES). You can easily test this by creating a test dialog with 2 buttons. On the first button create a thread and on the second button end the thread. Rapidly press the buttons and observe the newly created thread sometimes has the same handle value in your traced output. It is the same for window handles... when they are closed the same value can be assigned to a window created in the near future. An excerpt from: The Birth of a Thread: CreateThread[^] Please do not make any assumptions about this identifier; all that is guaranteed is that while the thread is running, no other thread will ever have the same ID. The ID may be recycled later on after the thread has terminated. Multithreading for Rookies[^] Give Me a Handle, and I'll Show You an Object[^] 1.) The benefit of your option is the engineer does not need to call DuplicateHandle. On the negative side your option requires the engineer to manually perform the thread cleanup. 2.) The benefit of the other option is the engineer does no cleanup because m_bAutoDelete defaults to TRUE. On the negative side the engineer has to call DuplicateHandle and then CloseHandle when he is done waiting. Anyway, this debate is meanlingless. If the presented scenario is what is actually occuring then both options presented are good options. This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience. Best Wishes, -David Delaune

            R Offline
            R Offline
            Roger Stoltz
            wrote on last edited by
            #13

            Randor wrote:

            The NT kernel recycles both window and thread identifiers (HANDLES).

            Yep, I know that it does. I don't see how this is relevant in this scenario though; even if the handle gets recycled it can only have one state in the aspect of valid or invalid when ::WaitForSingleObject() is called, which would mean that if the handle should happen to be invalid when ::WaitForSingleObject() is called it would return WAIT_FAILED. That's why I still think my previous statement is correct even though you seem to think not. Additionally, as I understood it, the OP waits on the thread handle before creating another worker thread (as he should).

            Randor wrote:

            If the presented scenario is what is actually occuring then both options presented are good options.

            Of course! :-D

            Randor wrote:

            Anyway, this debate is meanlingless.

            Naah, you provided a perfectly acceptable meaning yourself:

            Randor wrote:

            This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience.

            Exactly and I really enjoyed our little discussion.

            "It's supposed to be hard, otherwise anybody could do it!" - selfquote
            "High speed never compensates for wrong direction!" - unknown

            L 1 Reply Last reply
            0
            • R Roger Stoltz

              Randor wrote:

              The NT kernel recycles both window and thread identifiers (HANDLES).

              Yep, I know that it does. I don't see how this is relevant in this scenario though; even if the handle gets recycled it can only have one state in the aspect of valid or invalid when ::WaitForSingleObject() is called, which would mean that if the handle should happen to be invalid when ::WaitForSingleObject() is called it would return WAIT_FAILED. That's why I still think my previous statement is correct even though you seem to think not. Additionally, as I understood it, the OP waits on the thread handle before creating another worker thread (as he should).

              Randor wrote:

              If the presented scenario is what is actually occuring then both options presented are good options.

              Of course! :-D

              Randor wrote:

              Anyway, this debate is meanlingless.

              Naah, you provided a perfectly acceptable meaning yourself:

              Randor wrote:

              This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience.

              Exactly and I really enjoyed our little discussion.

              "It's supposed to be hard, otherwise anybody could do it!" - selfquote
              "High speed never compensates for wrong direction!" - unknown

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #14

              Roger Stoltz wrote:

              I don't see how this is relevant in this scenario though

              Is it *very* relevant. I am asserting that there is a small chance that immediately following thread termination it is possible for the same identifier to be assigned to another thread or kernel object. If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock. The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you. As I have previously mentioned both of our excellent recommendations will avoid the deadlock. Best Wishes, -David Delaune

              C R 2 Replies Last reply
              0
              • L Lost User

                Roger Stoltz wrote:

                I don't see how this is relevant in this scenario though

                Is it *very* relevant. I am asserting that there is a small chance that immediately following thread termination it is possible for the same identifier to be assigned to another thread or kernel object. If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock. The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you. As I have previously mentioned both of our excellent recommendations will avoid the deadlock. Best Wishes, -David Delaune

                C Offline
                C Offline
                Chesnokov Yuriy
                wrote on last edited by
                #15

                Well, what I have is a button click code: 1. if (m_SomeThread != 0) goto 2. 2. WaitForSingleObject(m_SomeThread->m_hThread, INFINITE); 3. m_SomeThread = AfxBeginThread(...) The thread starts immediatly. What I understood is if you create thread suspended and set autodelete to false, it will not be destroyed as the thread finishes. In that case m_SomeThread->m_hThread will be valid and will not hang the GUI? In that case it needs additional explicit thread destruction between 2. and 3. clauses.

                Чесноков

                L 1 Reply Last reply
                0
                • C Chesnokov Yuriy

                  Well, what I have is a button click code: 1. if (m_SomeThread != 0) goto 2. 2. WaitForSingleObject(m_SomeThread->m_hThread, INFINITE); 3. m_SomeThread = AfxBeginThread(...) The thread starts immediatly. What I understood is if you create thread suspended and set autodelete to false, it will not be destroyed as the thread finishes. In that case m_SomeThread->m_hThread will be valid and will not hang the GUI? In that case it needs additional explicit thread destruction between 2. and 3. clauses.

                  Чесноков

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #16

                  Hi Yuriy, Yes you understand correctly. The thread handle will be valid if m_bAutoDelete is set to FALSE. You will need to perform cleanup yourself of the m_SomeThread object. Best Wishes, -David Delaune

                  1 Reply Last reply
                  0
                  • L Lost User

                    Roger Stoltz wrote:

                    I don't see how this is relevant in this scenario though

                    Is it *very* relevant. I am asserting that there is a small chance that immediately following thread termination it is possible for the same identifier to be assigned to another thread or kernel object. If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock. The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you. As I have previously mentioned both of our excellent recommendations will avoid the deadlock. Best Wishes, -David Delaune

                    R Offline
                    R Offline
                    Roger Stoltz
                    wrote on last edited by
                    #17

                    Randor wrote:

                    As I have previously mentioned both of our excellent recommendations will avoid the deadlock.

                    :-) David, no offence taken! I find it interesting and there's a possibility that someone might learn something and it could be me. ;P However, I think you have misread my previous post (or possibly posts). I figure this as I am still under the impression that the OP waits on the thread handle before spawning a new thread, as I've stated previously. - or - Do you really mean that you have experienced a scenario where you have a handle that:

                    • you provide as argument to e.g. ::WaitForSingleObject()
                    • is valid so the waiting function doesn't return WAIT_FAILED immediately
                    • has not assumed a signalled state (which would make the waiting function return immediately)
                    • becomes signalled, closed and recycled behind scenes

                    in a way that makes the waiting function hang? (This is how I interpret your statement.) I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.

                    Randor wrote:

                    If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock.

                    If you are able to do that and wait on the thread handle before creating a new thread, I'd be delighted to see it. I will even try and create such an abomination myself. But if this is the case I don't see how any of our proposed solutions may prevent this deadlock.

                    Randor wrote:

                    The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you.

                    Well, I wasn't confused until I read the underlined part above. But the confusion is more about what you mean rather than whether a handle is valid or invalid.

                    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                    "High speed never compensates for wrong direction!" - unknown

                    L 1 Reply Last reply
                    0
                    • R Roger Stoltz

                      Randor wrote:

                      As I have previously mentioned both of our excellent recommendations will avoid the deadlock.

                      :-) David, no offence taken! I find it interesting and there's a possibility that someone might learn something and it could be me. ;P However, I think you have misread my previous post (or possibly posts). I figure this as I am still under the impression that the OP waits on the thread handle before spawning a new thread, as I've stated previously. - or - Do you really mean that you have experienced a scenario where you have a handle that:

                      • you provide as argument to e.g. ::WaitForSingleObject()
                      • is valid so the waiting function doesn't return WAIT_FAILED immediately
                      • has not assumed a signalled state (which would make the waiting function return immediately)
                      • becomes signalled, closed and recycled behind scenes

                      in a way that makes the waiting function hang? (This is how I interpret your statement.) I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.

                      Randor wrote:

                      If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock.

                      If you are able to do that and wait on the thread handle before creating a new thread, I'd be delighted to see it. I will even try and create such an abomination myself. But if this is the case I don't see how any of our proposed solutions may prevent this deadlock.

                      Randor wrote:

                      The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you.

                      Well, I wasn't confused until I read the underlined part above. But the confusion is more about what you mean rather than whether a handle is valid or invalid.

                      "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                      "High speed never compensates for wrong direction!" - unknown

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #18

                      Hi Roger,

                      Roger Stoltz wrote:

                      Do you really mean that you have experienced a scenario where you have a handle that:

                      Let me clarify the scenario I am presenting: 1.) Engineer creates a CWinThread object with m_bAutoDelete set to TRUE. 2.) CWinThread is started. 3.) A context switch takes place in GUI thread. 4.) CWinThread completes and exits and the handle is dereferenced. 5.) GUI thread resumes from context switch. 6.) GUI calls WaitForSingleObject on the CWinThread->m_hThread with INFINITE. 7.) The handle is a valid handle, another object has been assigned this identifier. 8.) WaitForSingleObject never returns. Yes, I have encountered this before in the real world. You can produce an application which exibits this handle recyling deadlock behavior.

                      Roger Stoltz wrote:

                      I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.

                      I'm surprised that you have not read about this before. Its the same thing with window handles. I have noticed that you often reference Dr. Joseph Newcomer in your posts. What is occuring under the hood is essentially the same principles of the flaw described in Avoiding Multiple Instances of an Application[^] and window handles. Window handles can be closed and/or re-assigned to other windows. This can lead to deadlocks/race conditions. It is the essentially the same for thread/process handles. Handles cannot always be relied upon and they may be valid, invalid or re-assigned. You can probably find other software engineers describing this flaw: DuplicateHandle CWinThread Newcomer[^] Best Wishes, -David Delaune

                      R 1 Reply Last reply
                      0
                      • L Lost User

                        Hi Roger,

                        Roger Stoltz wrote:

                        Do you really mean that you have experienced a scenario where you have a handle that:

                        Let me clarify the scenario I am presenting: 1.) Engineer creates a CWinThread object with m_bAutoDelete set to TRUE. 2.) CWinThread is started. 3.) A context switch takes place in GUI thread. 4.) CWinThread completes and exits and the handle is dereferenced. 5.) GUI thread resumes from context switch. 6.) GUI calls WaitForSingleObject on the CWinThread->m_hThread with INFINITE. 7.) The handle is a valid handle, another object has been assigned this identifier. 8.) WaitForSingleObject never returns. Yes, I have encountered this before in the real world. You can produce an application which exibits this handle recyling deadlock behavior.

                        Roger Stoltz wrote:

                        I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.

                        I'm surprised that you have not read about this before. Its the same thing with window handles. I have noticed that you often reference Dr. Joseph Newcomer in your posts. What is occuring under the hood is essentially the same principles of the flaw described in Avoiding Multiple Instances of an Application[^] and window handles. Window handles can be closed and/or re-assigned to other windows. This can lead to deadlocks/race conditions. It is the essentially the same for thread/process handles. Handles cannot always be relied upon and they may be valid, invalid or re-assigned. You can probably find other software engineers describing this flaw: DuplicateHandle CWinThread Newcomer[^] Best Wishes, -David Delaune

                        R Offline
                        R Offline
                        Roger Stoltz
                        wrote on last edited by
                        #19

                        Okay David, now I know what you mean and of course you're right. I am aware if the scenario you're describing, or perhaps I should put it as "I have been"... :~ I've used the technique I described earlier (CWinThread::m_bAutoDelete blah blah) for a rather long time (must be almost a decade :doh: ) which saves me from a lot of troubles, including this one. I just forgot one of the reasons why I always use this technique and had a hard time putting it together in this context. :-\

                        Randor wrote:

                        I'm surprised that you have not read about this before.

                        Well, I take that as a compliment. :-O But in my defence I have to mention that until your last post I interpreted your statement as the handle provided to the waiting function indeed was a valid handle to the worker thread, but it got recycled during the time one thread was waiting on the handle and that caused the waiting function to hang. That's what made me "seriously doubt it" since it would make the whole synchronization mechanism unreliable. So it turns out I misunderstood you, to my relief. I'm grateful for the reminder David, thanks.

                        "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                        "High speed never compensates for wrong direction!" - unknown

                        L 1 Reply Last reply
                        0
                        • R Roger Stoltz

                          Okay David, now I know what you mean and of course you're right. I am aware if the scenario you're describing, or perhaps I should put it as "I have been"... :~ I've used the technique I described earlier (CWinThread::m_bAutoDelete blah blah) for a rather long time (must be almost a decade :doh: ) which saves me from a lot of troubles, including this one. I just forgot one of the reasons why I always use this technique and had a hard time putting it together in this context. :-\

                          Randor wrote:

                          I'm surprised that you have not read about this before.

                          Well, I take that as a compliment. :-O But in my defence I have to mention that until your last post I interpreted your statement as the handle provided to the waiting function indeed was a valid handle to the worker thread, but it got recycled during the time one thread was waiting on the handle and that caused the waiting function to hang. That's what made me "seriously doubt it" since it would make the whole synchronization mechanism unreliable. So it turns out I misunderstood you, to my relief. I'm grateful for the reminder David, thanks.

                          "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                          "High speed never compensates for wrong direction!" - unknown

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #20

                          Hi Roger, Now I am uncertain if this was the problem Yuriy was having. I just read the entire thread again and noticed that in this post[^] Yuri states that "99% of cases the thread is already terminated, when the WaitForSingleObject() is called." :doh: I am starting to think there may have been a serious design flaw. I guess we should have asked to see some code. :) Anyway I am leaving the office soon. Have a good night, -David Delaune

                          R 1 Reply Last reply
                          0
                          • L Lost User

                            Hi Roger, Now I am uncertain if this was the problem Yuriy was having. I just read the entire thread again and noticed that in this post[^] Yuri states that "99% of cases the thread is already terminated, when the WaitForSingleObject() is called." :doh: I am starting to think there may have been a serious design flaw. I guess we should have asked to see some code. :) Anyway I am leaving the office soon. Have a good night, -David Delaune

                            R Offline
                            R Offline
                            Roger Stoltz
                            wrote on last edited by
                            #21

                            Well, the OP's problem could still be the one we've been discussing. There is a possibility that the handled gets recycled between thread termination and the call to ::WaitForSingleObject(). When he claims that the thread is already terminated in 99% of the cases I doubt he really checks the return value; the wait may have failed since the handle has been closed but he doesn't care because it means that the thread doesn't run any longer. As I wrote earlier I still think he has introduced a race condition where the worker thread somehow sends a message to the main thread instead of posting. If the main thread has already assumed its waiting state on the thread handle the deadlock is a reality. This is in my opinion the most common reason for deadlocks when it comes to multithreading and would most definitely result in the behaviour he has described. It may be that he's calling a framework function that disguises the ::SendMessage() call. The probability for a design flaw I guess is very close to 100%. I will have a good night; it's almost 1:00AM in Sweden and I'm about to hit the sack. I wish you a good night as well! -- Rog

                            "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                            "High speed never compensates for wrong direction!" - unknown

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups