Need help with writing progress bar dialog, with smooth marquee, on one thread

simonx 126 Reputation points
2024-04-12T10:02:57.8+00:00

Hi - my Win32, MFC, Visual C++ application frequently has to perform operations which can take a long time. I want the user to be able to see a progress dialog with a marquee and a Cancel button while these are happening. I would like the marquee to move swiftly and smoothly along the bar. I can't find a good way to get this to work. I am currently using the MFC CProgressCtrl in marquee mode. As I understand it, my options are:

(1) Display the dialog on the main (GUI) thread, and do the long operation on a background thread.

(2) Display the dialog on the main (GUI) thread, do the long operation on the same thread, but regularly pump the message queue so that the marquee animates (in tests I have found that if I don't pump the queue, the marquee is motionless; and of course if the user clicks on the Cancel button, nothing will happen).

Neither of these options is very satisfactory for me. The various long operations were not designed to run on a separate thread, and I couldn't safely move them onto a background thread without doing a lot of work which would take time that I do not have (and there might be other reasons why this option will not work). But option (2) is not very satisfactory either. The long operations are frequently very complex, with numerous sub-operations (and sub-sub-operations), each of which can also be long. So I would need to scatter the code for pumping the message queue all over the place. Even if I do that, my concern is that (a) all this message queue pumping could make the long operations considerably longer (b) inevitably, the rate at which the queue gets pumped will be inconsistent, and the marquee may look jerky and not smooth as a result when it moves (again, this is what I have found when testing possible solutions).

A solution that I would prefer is the following:

Option (3): I put up the dialog with a marquee that is somehow implemented as an animation which moves smoothly, even if I when I am not pumping the message queue. Presumably in order for that to work, the animation would not be running on my main GUI thread. I would still have to pump the message queue from time-to-time to detect if the Cancel button is pressed. But I wouldn't worry about pumping it constantly to get that smooth marquee look. I would aim to pump it just enough to be able to detect a Cancel button press in a reasonable time. Which should be much easier to achieve (a slight pause after a Cancel button is pressed, before you get a response, is acceptable).

Of course an even nicer solution would be if the entire Progress dialog could be running on a separate thread to my main application thread (and to the normal main GUI thread). Call this option (4). In this option the marquee could be fast and smooth and the Cancel button could be super responsive. I'm guessing that that is not possible though.

So my question is: are options (3) or (4) possible with the CProgressCtrl or with any other control? If so, how? All help very much appreciated.

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,731 questions
{count} votes

Accepted answer
  1. RLWA32 45,571 Reputation points
    2024-04-15T12:05:00.39+00:00

    Option 4 to run a progress dialog on a separate thread can be done with MFC. However, while the progress dialog will be unencumbered by the long-running operation on the UI thread the need to pump messages on the UI thread remains. In the illustration below, the simulated long-running operation does not pump messages so Windows will show that the main window is not responding. The progress dialog continues until the long-running operation is completed or cancelled.ThreadedProgress

    You can find guidance for MFC and Mulltithreading here - Multithreading with C++ and MFC

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. simonx 126 Reputation points
    2024-04-15T14:42:35.3333333+00:00

    Hi all - thank you for your answers, but especially RLWA32. I am inclined to go for option 4 and put the progress dialog on a second UI thread. It's a good point that you still need to pump messages on the main GUI thread to prevent Windows thinking that it's 'not responding'. But the pumping wouldn't have to be nearly as frequent as would be needed to get a smooth scrolling marquee; so I still think this is a good option.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.