Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best strategy to update QTableView with data in real-time from different threads

I have application that for now starting few threads ( like 5 – 10 ) to collect data from different source .
They are separated from the main GUI thread so I don’t feel any slowness in the GUI and I can keep working while the background threads are working . all great .
But now I like to be able to display the results in QTableView in my main GUI . the data is strings allots of them and it can have between 10,000 to 100,000 results that supposed to be upto 100,000 rows in the QTableView.

My question is what is the best way to update the Table in the Main GUI from the threads so TH GUI won’t be slow or idle while updating.

like image 293
user63898 Avatar asked Nov 28 '12 12:11

user63898


Video Answer


1 Answers

This is how I would do it:

Add a signal to the worker threads that is emitted each time a new batch of data is ready. Connect this signal to a slot defined in the main GUI thread using Qt::QueuedConnection. This slot should collect the processed data from the worker threads and insert it into the table's model. Model should be naturally also in the GUI thread.

Update 1

More detailed explanation. You already got the threads down so all you'll have to do is to expand them a little. Example:

// NOTE:
// In this example I'm assuming that the thread continues to work after
// preparing first batch of data. One thread can prepare multiple batches
// over time. If that's not the case for you then you can probably
// safely ignore mutex stuff and intermediary tmp variables.
class MyWorker : public QThread
{
    // ...
    public:
        void run()
        {
            while (bWork)
            {
                QList<MyData> myData;
                // Populate 'myData' variable with your data.
                // ...

                // Now, store myData in more persistent buffer and emit the
                // ready signal.
                dataBatchMutex.lock();
                dataBatch.append(myData);
                dataBatchMutex.unlock();
                emit dataBatchReady();
            }
        }

        QList<MyData> popLastBatch()
        {
            QMutexLocker l(&dataBatchMutex);
            QList<MyData> tmp = dataBatch;
            dataBatch.clear();
            return tmp;
        }

    signals:
        void dataBatchReady();

    private:
        QMutex dataBatchMutex;
        QList<MyData> dataBatch;
};

We have the worker thread. Now about the GUI thread:

  1. Create your worker threads objects.
  2. Connect the dataBatchReady() signal to a slot in the GUI thread. Remember to use Qt::QueuedConnection.
  3. Start the threads.
  4. When that slot is executed you need to figure out which worker thread has the new data. You may pop them all (not very efficient) or you may add additional method to the worker to find out if the dataBatch field is not empty. You may also invent other way to figure out which thread emitted the signal - that's up to you to figure out.
  5. When you figure out the thread just call the popLastBatch() on that thread and add the returned list to the model. The model will take care of the rest. If you still have performance issues then refer to tHand's response.

Note: I didn't test the code so it may contain some obvious errors. You should get the idea, though.

like image 92
ZalewaPL Avatar answered Sep 18 '22 04:09

ZalewaPL