[RESOLVED] MFC C++ multiple OnSetActive() calls happening at once
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 19

Thread: [RESOLVED] MFC C++ multiple OnSetActive() calls happening at once

  1. #1
    Join Date
    May 2013
    Location
    West Warwick, RI
    Posts
    8

    [RESOLVED] MFC C++ multiple OnSetActive() calls happening at once

    I have a bit of an odd issue. I maintain a piece of software that appears to be handling multiple calls to OnSetActive() at once.

    The problem manifests when performing a large image operation. OnSetActive forces the form to redraw, and a lengthy image operation takes place. Before it is finished OnSetActive() is called again. I've come to this conclusion by putting modal "Before" and "After" AfxMessageBoxes before and after the image operation. You'll see "Before" display multiple times.
    From there, I replaced the image operation with a Sleep().

    AfxMessageBox("Before");
    Sleep(30000);
    AfxMessageBox("After");

    and the same thing happened.

    Note: This only happens when running the release, this does not happen while debugging.

    Aside from the obvious flaw that a lengthy operation is being performed that freezes the program.. can someone tell me how what I'm witnessing is possible? If the AfxMessageBox is modal, how is it possible for OnSetActive() to run again before the second message box is reached? Are the message handlers multi-threaded by nature?

    I tried to reproduce this in a demo environment, but was unable to. Does anybody have any insight into what might be causing this?

  2. #2
    ovidiucucu's Avatar
    ovidiucucu is offline Moderator/Reviewer Power Poster
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,059

    Re: MFC C++ multiple OnSetActive() calls happening at once

    1. Do not use AfxMessageBox for debugging purpose. Use TRACE macros instead.
    2. Do not use OnSetActive for drawing purpose. Handle WM_PAINT instead.
    3. Do not call Sleep function for simulating long operations. It simply suspends the current thread.
    Ovidiu Cucu
    "When in Rome, do as Romans do."
    Visit: Microsoft Virtual Academy
    Follow: https://twitter.com/#!/ovidiucucu
    My blog: http://codexpert.ro/blog/author/ovidiu-cucu/

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,070

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Quote Originally Posted by cwhittier View Post
    Aside from the obvious flaw that a lengthy operation is being performed that freezes the program.. can someone tell me how what I'm witnessing is possible? If the AfxMessageBox is modal, how is it possible for OnSetActive() to run again before the second message box is reached? Are the message handlers multi-threaded by nature?
    The PSN_SETACTIVE is sent by Property Sheet control. It seems the control re-sends the message in case it considers the previous message lost due to some reason. The lengthy operation (or Sleep) you do in GUI thread makes it think that, as the control does not receive the message result within predefined period. So you should move your operation to a worker thread, and respond to the event instantly.

    As to message handlers and message box, I do not understand why would you be surprised. Message box modality only suspends the thread's message queue pumping. But it does not affect the way how SendMessageCallback or SendNotifyMessage works.
    Best regards,
    Igor

  4. #4
    Join Date
    May 2013
    Location
    West Warwick, RI
    Posts
    8

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Thanks for the response Igor. What you are describing is what I believed is happening as well, I just couldn't find any documentation or forum posts to confirm it. Is this just an observation of yours or is there something documented that says there is a predefined period your function has to return, otherwise it will just run again? That doesn't seem right to me.

    The other thing that I still can't wrap my head around though, is how the second call is executing at the same time that the first call is suspended. My GUI is suspended as well while the long operation is happening, so it appears the entire program is tied to the single thread, how can a message in the message queue even be processed if the entire program is hung up?

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,070

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Good questions, and I believe all of them should be directed to MS. What I said is just my in-mind how-it-would-be construct based on my many years of programming Windows, and I never saw this documented outright. There might be some insights from former MS employees that nowadays blog here and there, but yet again, never saw anything like that.
    Best regards,
    Igor

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    11,473

    Re: MFC C++ multiple OnSetActive() calls happening at once

    I would be inclined not to worry about the strange behavior and move to code up a worker thread to do the lengthy operation. If you prefer, consider using QueueUserWorkItem and have windows do the threading for you.

  7. #7
    Join Date
    May 2013
    Location
    West Warwick, RI
    Posts
    8

    Re: MFC C++ multiple OnSetActive() calls happening at once

    I'm not scared of implementing a worker thread. I'd prefer it, most of my issue here is that this code is part of a 10+ year old project that is being maintained, and the larger the change, the larger the risk that I break something else that was dependent on the code I move. I think implementing the thread would have the same result - even if the parent thread isn't hung up waiting for the long operation, it still needs to loop and wait for my worker thread to complete, as this operation is currently a requirement of OnSetActive(). If the assumptions stated above about the message handler 'timeout' are correct, then my issue should still occur, because OnSetActive() hasn't returned quickly enough.

    Again, I realize that my main problem is that we currently require OnSetActive() to perform this long operation, which is bad design - I'm fully aware of that. I'm just trying to understand what is happening that can cause the behavior I'm seeing, it seems like it should be impossible. When a single thread starts executing more than one function at the same time, it worries me a bit, as I can't guarantee how the program will execute.

  8. #8
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    11,473

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Quote Originally Posted by cwhittier View Post
    even if the parent thread isn't hung up waiting for the long operation, it still needs to loop and wait for my worker thread to complete, as this operation is currently a requirement of OnSetActive().
    The main thread doesn't need to loop to wait for a worker thread to finish other than the normal message pump type of loop. Generally, some ui controls are disabled while the worker thread is working, and the worker thread would post a message to the ui thread when it's completed its work. The ui picks up the message and uses the data in the worker thread (or shared data) and also reenables the ui controls. With regard to OnSetActive, this is separate from what the worker thread is doing and shouldn't impact your program flow. In other words, your program could be doing some work in a worker thread, and a user switch between your application and another app, and the worker thread shouldn't be interrupted. If OnSetActive is getting in the way of things, it might indicate a problem with the design.

    You do have the option of running the long running operation all in the main UI thread, but you'll need to pump messages every so often inside code performing the work. That way, the UI will remain responsive. However, if you plan to allow the user to have a great deal of control over the long running operation (like starting, pausing, stopping, etc.) then you might find it's easier to create the worker thread rather than trying to control the operation through the main ui thread.

    Lastly, keep in mind that the AfxMessageBox calls are going to mess with the OnSetActive of the parent window.

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,604

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Quote Originally Posted by cwhittier View Post
    ... even if the parent thread isn't hung up waiting for the long operation, it still needs to loop and wait for my worker thread to complete, as this operation is currently a requirement of OnSetActive(). If the assumptions stated above about the message handler 'timeout' are correct, then my issue should still occur, because OnSetActive() hasn't returned quickly enough.
    It sounds like this application was bad designed.
    And note that "the parent thread" should not "wait for the long operation", nor "needs it to loop and wait for my worker thread".
    The main thread should live its own life! Then when worker thread would posts (note: "posts", not "sends"!) some user defined message notifying the main thread that something had been changed, the main thread would update its UI and perhaps something else...

    For more info about using worker threads see this essay: Using Worker Threads
    Last edited by VictorN; May 10th, 2013 at 03:56 AM. Reason: Quote was added
    Victor Nijegorodov

  10. #10
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    11,473

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Phew, I had to recheck to make sure I didn't say send instead of post.

  11. #11
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,604

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Well, I edited my previous post to make it clear it was a response to OP's post not to Arjay's one!
    PS: I hadn't read Arjay's post until I posted my own one...
    Victor Nijegorodov

  12. #12
    Join Date
    May 2013
    Location
    West Warwick, RI
    Posts
    8

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Quote Originally Posted by VictorN View Post
    It sounds like this application was bad designed.
    It sure does, doesn't it!

    Arjay's alternative makes sense, so saying that using a worker thread wouldn't help the issue was incorrect on my part. If it was implemented that way, then the OnSetActive() could return quickly.

    I think we're getting slightly off topic though. I'm sure there are a number of ways I can work around the issue, but what this post is primarily about, is trying to understand the issue itself. This actually isn't the first time I've encountered this problem - though the first time I encountered it I ended up making it so the long operation happens somewhere else. What I'm really trying to understand, is why/how the OnSetActive() method "times out", or how it can be called a second time before the first call finishes? I think understanding this is important. What's the limitation here, and how is it measured? I don't like modifying design (albeit a bad one that I was stuck with) or implementing a work-around for an issue that I don't fully understand.

    Why can't I find any information on this? You'd think if a message handler function had this timeout, then the net should be flooded with information of people doing long operations after a button press, and having it run again.

    Is it possible my assumption about what's happening here is incorrect, and it's the AfxMessageBoxes causing a problem? I can change this and see if the problem still exists, but I do get hung up forever without message boxes in the code, which makes me believe that the issue is still occurring. I'm really just looking for an explanation, because the symptoms here still don't make sense.

  13. #13
    Join Date
    May 2013
    Location
    West Warwick, RI
    Posts
    8

    Re: MFC C++ multiple OnSetActive() calls happening at once

    UPDATE: I've removed the AfxMessageBox calls, and replaced them with file writes (TRACE wouldn't work because this problem doesn't manifest in debug). This appears to have made the behavior I was witnessing go away. I am still curious to know what was happening. I could understand if the AfxMessageBoxes were causing the focus to change, and therefore triggering another OnSetActive() when the form regained focus, but I'm still lost about how the new OnSetActive() message can get handled before the previous one completes.

    Is there something about the way the message box gets handles that triggers a DoEvents scenerio, that could cause the new OnSetActive message to be handled before returning to complete the first call?

  14. #14
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,843

    Re: MFC C++ multiple OnSetActive() calls happening at once

    I get very suspicious of problems that happen in release and don't in debug and when the problem changes or seems to go away when unrelated code is changed. This has the smell of a memory corruption issue.
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  15. #15
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    11,473

    Re: MFC C++ multiple OnSetActive() calls happening at once

    Quote Originally Posted by cwhittier View Post
    UPDATE: I've removed the AfxMessageBox calls, and replaced them with file writes (TRACE wouldn't work because this problem doesn't manifest in debug). This appears to have made the behavior I was witnessing go away. I am still curious to know what was happening. I could understand if the AfxMessageBoxes were causing the focus to change, and therefore triggering another OnSetActive() when the form regained focus, but I'm still lost about how the new OnSetActive() message can get handled before the previous one completes.

    Is there something about the way the message box gets handles that triggers a DoEvents scenerio, that could cause the new OnSetActive message to be handled before returning to complete the first call?
    AfxMessageBox calls do take focus, so when they are dismissed the previous window will regain focus. It is puzzling about the order of when the set active messages occur, but keep in mind that you are sleeping the ui thread for a long period of time and your original code had an AfxMessageBox immediately coming out of the sleep. When you block the main thread, all sorts of messages get queued or ignored or their priorities get changed - some messages get processed before others, so it becomes very difficult to determine what exactly is going on (and there are additional checks in debug mode that don't happen in release, so that complicates things as well).

    So the bottom line here is to not block the main thread for any extended period. You can pump messages in the middle of your operation code, or use a worker thread.

    Last comment, in terms of using TRACE, keep in mind that if you are debugging inside the VS IDE, the trace statements will show up in the output window. If you are running the debug version of your app outside the debug window, the trace statements will show up in a tool like dbgview.exe. So even though you don't have a console app, you can still get trace output (and unlike AfxMessageBox, TRACE won't effect window focus).

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center