jaho
jaho

Reputation: 4992

How to handle signal flood from another thread in Qt

tl;dr: I have a QThread which sends a signal to the main thread whenever new data is available for processing. Main thread then acquires, processes and displays the data. The data arrives more often the the main thread is able to process it resulting in frozen GUI and eventually a stack overflow (yay!).

Details

My application acquires frames from a camera for processing and displaying. The camera notifies when the new frame is available through a windows event. I have a thread which periodically checks for these events and notifies the main thread when new frame is available for grabs:

void Worker::run()
{
    running_ = true;

    while (running_)
    {
        if (WaitForSingleObject(nextColorFrameEvent, 0) == WAIT_OBJECT_0)        
            emit signalColorFrame();        

        usleep(15);
    }
}

signalColorFrame is connected to a slot in Camera class which gets the frame from camera, does some processing and sends it to MainWindow which draws it to the screen.

void Camera::onNewColorFrame()
{    
    getFrameFromCamera();
    processFrame();
    drawFrame();
}

Now if that method completes before the next frame is available, everything works fine. As the processing gets more complex though the Camera class receives new signals, before it's done with processing a previous frame.

My solution is to block signals from the worker thread for the time of processing and force the even loop to run in between with QCoreApplication::processEvents():

void Camera::onNewColorFrame()
{   
    worker_->blockSignals(true)
    getFrameFromCamera();
    processFrame();
    drawFrame();
    QCoreApplication::processEvents(); // this is essential for the GUI to remain responsive
    worker_->blockSignals(false);
}

Does that look like a good way of doing it? Can someone suggest a better solution?

Upvotes: 3

Views: 995

Answers (1)

evilruff
evilruff

Reputation: 4085

I think before you solve technical side you should consider to think about design side of your application. There are several ways your problem can be solved, but first you should decide what to do with frames which you dont have time to process in main thread. Are you going to skip them or save for later processing, but then you should realise that processing queue still must have certain size limits, so you anyway should decide what to do with 'out of bound' data.

I would personally prefer in such cases make some intermediate container which holds data which received somewhere, so your camera processing thread just notify collector that data received and collector decides if its going to store or skip data. And main loop as soon as it has time access collector in a form fetchNext() or fetchAll() depending on what you need and implements object processing.

Upvotes: 2

Related Questions