May 2, 2011

Julien M Julien M
Lab Rat
311 posts

Infinite loop and signal deluge

Page  
1

I have a problem with a loop in my code.
Basically I do this in a thread:

  1. while( !stop )
  2. {
  3.    textResult = someLongProcessing(); // this takes ~50ms
  4.    emit displayText(textResult);
  5. }
The signal is connected to the setValue() slot of a QLabel, so nothing really time consuming.

The problem is that sometimes someLongProcessing() returns immediately, causing the loop to emit a lot of signals.
My ram usage then increases a lot and the software crashes.

I can’t call processEvents() because I’m not in the main thread. Then what should I do?
I can not handle the issue slot-side, since it’s a qt slot.
If I add a sleep(5) in the loop it’s better, but how would I know that the computer it’s running on will need 5 or 10ms or even more to handle the setValue()…?

Thanks a lot for the help.

  • EDIT: I just found about Qt::BlockingQueuedConnection, could this be a good idea?

34 replies

May 2, 2011

Andre Andre
Robot Herder
6420 posts

I would simply make sure that you don’t emit your signal if it should not emit. Best place to stop such an overflow it as the source…

Is there some way for your process to know if the result is new or updated or something like that? If not, you could use a technique like this [developer.qt.nokia.com] to throttle your signal emissions, I guess.

May 5, 2011

Julien M Julien M
Lab Rat
311 posts

Andre wrote:
I would simply make sure that you don’t emit your signal if it should not emit.
In fact I always want to emit this signal. I “rephrased” my question in the first post.

May 5, 2011

HuXiKa HuXiKa
Lab Rat
83 posts

maybe this?

  1. while ( !stop ){
  2.  
  3.    bool finished = false;
  4.    finished = someLongProcessing(*textResult); // if you finshed parsing your text return true
  5.    if(finished)
  6.       emit displayText(textResult);
  7. }

 Signature 

If you can find faults of spelling in the text above, you can keep them.

May 5, 2011

Julien M Julien M
Lab Rat
311 posts

I don’t get it. With your finished boolean you just turn someLongProcessing() into a blocking call. But it is already blocking.

May 5, 2011

HuXiKa HuXiKa
Lab Rat
83 posts

Sorry forgot the stop = true; line.

  1. while ( !stop ){
  2.  
  3.    bool finished = false;
  4.    finished = someLongProcessing(*textResult); // if you finshed parsing your text return true
  5.    if(finished){
  6.       emit displayText(textResult);
  7.       stop = true;
  8.    }
  9. }

 Signature 

If you can find faults of spelling in the text above, you can keep them.

May 5, 2011

Julien M Julien M
Lab Rat
311 posts

This will break the loop. I don’t want to break the loop when someLongProcessing() returns true. You obviously did not understood my problem.

May 5, 2011

Franzk Franzk
Lab Rat
840 posts

It is generally only useful to update a text if it has actually changed, so assuming that some successive calls may produce the same text result:

  1. QString previousText;
  2. while (true) {
  3.     QString text = someLongProcessing();
  4.     if (previousText != text) {
  5.         previousText = text;
  6.         emit displayText(text);
  7.     }
  8. }

 Signature 

“Horse sense is the thing a horse has which keeps it from betting on people.”—W.C. Fields

http://www.catb.org/~esr/faqs/smart-questions.html

May 5, 2011

Julien M Julien M
Lab Rat
311 posts

I’m sorry but successive calls wont produce the same result.
There’s nothing to do with the event queue?

May 5, 2011

Scylla Scylla
Lab Rat
238 posts

QApplication::processEvents() helps?

May 5, 2011

Gerolf Gerolf
Hobby Entomologist
3287 posts

Hi neFast,

is this loop executed in a thread?
If yes, processEvents will never help.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

May 5, 2011

Julien M Julien M
Lab Rat
311 posts

Yes it is in a thread. What do you suggest?

May 5, 2011

Gerolf Gerolf
Hobby Entomologist
3287 posts

From that thread you have no influence on the main thread directly by calling processEvents etc. If you fill up the queue of one thread by another one, you have to think, whether it is the correct way for doing so.

Perhaps you should change the logic to something like this:

thread —> setText on intermediatObject —> emit signal

intermediatObject is a thread save object, which stores the last text and stores, whether the text was already read. If a text is set, it emits the signal, if after the last read there came no new text.

But that changes the logic completely…

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

May 5, 2011

Franzk Franzk
Lab Rat
840 posts

Another consideration is that the text might change quickly enough for the user not even to notice it. It would probably make sense to not let the longProcessThingy() control the text the user sees unless there’s an error of sorts. The current approach seems indeed too naive for successful operation.

 Signature 

“Horse sense is the thing a horse has which keeps it from betting on people.”—W.C. Fields

http://www.catb.org/~esr/faqs/smart-questions.html

May 26, 2011

Julien M Julien M
Lab Rat
311 posts

Sorry to bump this thread, but are there any best practice that I could find to solve my problem?

  • EDIT: I just found about Qt::BlockingQueuedConnection, could this be a good idea?

May 26, 2011

Franzk Franzk
Lab Rat
840 posts

If your thread can wait, sure, try that.

 Signature 

“Horse sense is the thing a horse has which keeps it from betting on people.”—W.C. Fields

http://www.catb.org/~esr/faqs/smart-questions.html

Page  
1

  ‹‹ not able to create my desired sizes and positions with QT Creator layouts      [Solved]GraphicsWidget & GraphicsScene - auto resizing ››

You must log in to post a reply. Not a member yet? Register here!