0

I have heavy task. I created QProgressBar for displaying that programm still work and runned heavy task in another thread using c++ std::thread class. But QProgressBar don't work, only window with QProgressBar starts. Here is the code:

QProgressBar progress;
progress.setRange(0, 0);
progress.show();
if (keyLength == 1024)
    std::thread(&RSA::generateKeys, &rsa, RSA::RSA_1024).join();
else if (keyLength == 2048)
    std::thread(&RSA::generateKeys, &rsa, RSA::RSA_2048).join();

Here is the result: enter image description here

  • 2
    And, where is the code, that signals the progress bar about changed status? Why are you setting your progress bar to undetermined state, instead of setting valid min/max values, and the signaling it whenever current value changes? – Algirdas Preidžius Mar 31 '17 at 20:40
  • it's should run and run without min and max value, like this http://doc.qt.io/qt-5/images/macintosh-progressbar.png –  Mar 31 '17 at 20:41
  • 1
    Please elaborate on _how_ do you suppose it does that? How should it run through 0-100% of progress bar length, in the correct amount of time, without any sort of signals on updated status? – Algirdas Preidžius Mar 31 '17 at 20:43
  • According to the [documentation](http://doc.qt.io/qt-5/qprogressbar.html#details): _If minimum and maximum both are set to 0, the bar shows a busy indicator instead of a percentage of steps._ However, there is not enough information in the question to judge if _busy indicator_ is shown, but, it's pretty clear, that progress bar shouldn't be (as shown in the question). – Algirdas Preidžius Mar 31 '17 at 20:45
  • @AlgirdasPreidžius http://www.screencapture.ru/uploaded/27/83/d2/2783d2Da.jpg –  Mar 31 '17 at 20:47
  • @AlgirdasPreidžius Yes, I wan't to see busy indicator, but I don't see it. –  Mar 31 '17 at 20:52

1 Answers1

2

This is not how things are done. :) Here you can see an example I have made that uses the Worker pattern (a separate thread that processes some heavy task and reports back to the UI). Here is how my application looks:

enter image description here

I use QThread (worker thread that contains an object that handles the processing) and I can only recommend you to do the same. You can also subclass QThread and override the run() method depending on what you really need however this is rarely the case.

PS: As an alternative you can use QRunnable (very useful for tasks that are done every once in a while which doesn't require a separate thread to be managed all the time). The problem with QRunnable is that it doesn't subclass QObject which means that you can't use the slot-signal mechanism to report back to the UI. Of course you can change that but it defeats the purpose of the runnable which is intended to be a very lightweight solution.

rbaleksandar
  • 8,713
  • 7
  • 76
  • 161
  • I don't understand, why I can't use c++ thread for this task? I don't want to report, how many task I done, I only want to report user, that task is still solving. –  Mar 31 '17 at 20:51
  • From what I understand you want the progress bar to report how far the task (in the separate thread) has been done, right? Reporting back to the UI requires you to use signals and for that `QThread` is the way to go. – rbaleksandar Mar 31 '17 at 21:26
  • @rbaleksandar A `QThread` is a thread handle. Just as you wouldn't modify a file handle class, you shouldn't modify `QThread` by deriving from it. If you want signals, derive from `QObject`, or forgo signals and queue calls directly to the receivers, [GCD-style](http://stackoverflow.com/a/21653558/1329652). You can emit signals, or queue slot calls, from any thread. `QThread` is not special in any way in this respect. – Kuba hasn't forgotten Monica Mar 31 '17 at 22:40
  • I haven't said "subclass QThread" at all. In fact if you actually check the link I have posted you will see that I use a `QObject` and move it to a generic instance of `QThread`. – rbaleksandar Apr 01 '17 at 01:00
  • I'm having trouble mapping the code you provide here to a non-toy context. If I am reading it correctly a QTimer is driving processing in chunks in the worker thread, rather than the worker thread looping over chunks of work and reporting back to the UI. In a non-toy context the worker is performing some computation inolving its own main loop or other control structure such that it can't naturally allow timer events to control it: it has local state being maintained in its call stack; a backgorund computation is not naturally a flat list of work chunks. – jwezorek Jun 23 '22 at 16:51
  • 1
    @jwezorek My example is very basic. If you have something more complicated running in the separate thread you will need a datastructure for example that will be accessed from both the Qt main thread and whatever context you are running in parallel. For example I recently created a Qt integration with the game engine Panda3D. Both have infinite main loops. In that case you have make a decision who's going to be the boss and use whatever mechanisms you have in the other to check periodically for changes. – rbaleksandar Jun 23 '22 at 18:13
  • 1
    In case of Panda3D integration and given it's a game engine with 3D rendering, I let Panda3D run it's main loop, while using a mediator `QObject` that handles communication between Qt and Panda3D and also manually check if there are pending events on Qt's side and process those in Panda3D's own task manager. Again it really depends on the problem at hand. Also for any shared data structure you need to ensure that it's thread-safe and triple check for possible racing conditions. – rbaleksandar Jun 23 '22 at 18:16
  • yeah, i get it. I'm just saying a more useful example would not use a QTimer like that. Instead just have the worker thread loop with a sleep. – jwezorek Jun 23 '22 at 18:31