user889030
user889030

Reputation: 4764

how to pass structure to QT thread

Am trying to pass data structure to QT thread and but no success.

here is what am doing and have done.

i prepare data for the thread, like this and then tried to pass prepared data to thread before starting.

void mytable::prepare_data(){
   // get table row count 
   int rowCount = ui->my_table_view->rowCount();    

  // create structure array  based on rowCount
  pnp_com_info pnp_data[rowCount];

  /* pnp_com_info structure defined it top of file below includes to make it global
    struct pnp_com_info{
      QString com_name = "";
      int x = 0;
      int y = 0;
      int angle = 0;
      bool status = false;
    };
  */

  // loop on table rows columns and load pnp_data with data of columns


// PROBLEM : how to pass pnp_data structure to thread side ?

 // can pass basic vars like
 RunJobThread->mynum = 10; 


// start QT thread 
RunJobThread->start();

 // std:: thread experiment
 // std::stdthreadtest(pnp_data,rowCount);

}

run_job_thread.h source code

#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H

#include <QObject>
#include <QThread>

class run_job_thread : public QThread
{
    Q_OBJECT
public:
    run_job_thread();

    void run();

    int mynum;

        struct pnp_com_info_thread{
          QString com_name = "";
          int x = 0;
          int y = 0;
          int angle = 0;
          bool status = false;
        };
    bool Stop;  // bool to stop the job
signals:
    void select_row_of_table_signal(int);
public slots:

};
#endif // RUN_JOB_THREAD_H

run_job_thread.cpp source code

#include "run_job_thread.h"
#include <QtCore>

run_job_thread::run_job_thread()
{

}

// run the thread
void run_job_thread::run(){

  qDebug() << "my num passed value is : "<<this->mynum;  // output : 10

    // Goal : loop on pnp_data structure and emit signal to table rows

    emit select_row_of_table_signal(5);
}

things i tried

instead of struct i tried to use other data containers like map, multimap, vectors but they give error , as am initializing pnp_com_info struct inside mytable::prepare_data() function based on rowCount which make it local and limited to prepare_data() function but with map,multimap,vector my plan was that they will be global and i will be able to access it from thread, however it not worked.

std::map<std::string, int,int,int> pnp_com_info;  // error: too many template arguments for class template 'map'
std::multimap<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'multimap'
std::vector<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'vector'

i also tried std::thread which was partial success , i mean it was working ok but looks like std::thread not works with QT GUI thread as upon running app GUI will go freez although std::thread was doing its job

Upvotes: 1

Views: 512

Answers (2)

Ricardo Ramirez
Ricardo Ramirez

Reputation: 21

I would suggest to do the following, because the declaration of the

pnp_com_info pnp_data[rowCount];

is inside a context i think their lifecycle will be lost once you leave it, other problem is that it would be really "unsafe" to create this kind of arrays and then pass it from one side to another. Therefore I would create a QList and then pass either a copy or the reference to the worker thread. So

1) Create a QList pnp_data, in the public part of mytable

2) Fill all data using a for loop as follows.

3) Create another QList pnp_data or a QList *pnp_data (if you want to use a copy or a pointer)

4) Then just pass either a copy or a reference to the worker thread.

Then it should look like this:

mytable.h source code

public: QList<pnp_com_info> pnp_data;

mytable.cpp source code

void mytable::prepare_data(){
   // get table row count 
   int rowCount = ui->my_table_view->rowCount();    



// HERE YOU LOAD ALL THE VALUES TO THE LIST
for(int i = 0; i<rowCount; i++){
pnp_com_info itemToInsert;
//FILL HERE THE itemToInsert
//Insert the item inside the list.
 pnp_data.append(itemToInsert);
}


// PROBLEM : how to pass pnp_data structure to thread side ?

 // Either pass it as a copy
 RunJobThread->pnp_data = pnp_data; 
//or as a reference
QList<pnp_com_info> *pnpDataPointer = &pnp_data;
RunJobThread->pnp_data_reference = pnpDataPointer;


// start QT thread 
RunJobThread->start();

 // std:: thread experiment
 // std::stdthreadtest(pnp_data,rowCount);

}

run_job_thread.h source code

#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H

#include <QObject>
#include <QThread>

class run_job_thread : public QThread
{
    Q_OBJECT
public:
    run_job_thread();

    void run();

            struct pnp_com_info_thread{
          QString com_name = "";
          int x = 0;
          int y = 0;
          int angle = 0;
          bool status = false;
        };

    QList<pnp_com_info> pnp_data; //This one if you create a copy
    QList<pnp_com_info> *pnp_data_reference; //This if you want a pointer



    bool Stop;  // bool to stop the job
signals:
    void select_row_of_table_signal(int);
public slots:

};
#endif // RUN_JOB_THREAD_H

I hope this helps.

Upvotes: 2

Toby Speight
Toby Speight

Reputation: 30876

First, don't subclass QThread to create a worker - re-read How To Really, Truly Use QThreads; The Full Explanation by Maya Posch. You will find it much more manageable to create a worker object and connect the threads started() to your worker's main method, and the worker's signals to the thread's quit() and deleteLater().

Then, it should be much more straightforward to pass your data to the worker before it's moved to the thread, or to use a signal connection if it needs to be passed when the worker is running (remember to register your structure with the meta-object system for that).

Upvotes: 1

Related Questions