How to track task progress of threads in a thread pool



  • I have an app that launches tasks in threads from a thread pool. The code for the task executes from the run method and emits appropriate signals to send task data back to the GUI thread.

    Each thread when launched displays its own row of a label progress bar and LED indicator.

    How do I identify a particular thread to access the data it is sending to the GUI?

    I understand that the thread pool manages the threads. Should the thread pool be exchanged for QThread?

    Thanks in advance


  • Moderators

    Hi,

    [quote]How do I identify a particular thread to access the data it is sending to the GUI?[/quote]Do you want to identify the thread or the task?

    When you send signals back to the GUI thread, you can include the ID in your signals.



  • [quote author="JKSH" date="1392170995"]Hi,

    [quote]How do I identify a particular thread to access the data it is sending to the GUI?[/quote]Do you want to identify the thread or the task?

    When you send signals back to the GUI thread, you can include the ID in your signals.[/quote]

    Hi,

    Thanks for the quick reply. The task is all the code in the run method. So the task is the same for any and all threads. I wish to identify when data is present for the running task that it is sent to the gui for the particular thread that the data is present for. Additionally, if I have a scroll area with 10 rows of widgets where each row represents a running thread, How do I associate a row with a thread?

    Maybe a long reply but I wanted to clarify.

    Thanks


  • Moderators

    A QThreadPool reuses the same thread to run many QRunnables.

    For example, suppose your pool has 2 threads (called Thread 1 and Thread 2), but you start 10 QRunnables.

    • Thread 1 runs QRunnable 1, and Thread 2 runs QRunnable 2. The other 8 QRunnables wait in the queue.
    • When Thread 1 finishes QRunnable 1, it starts running QRunnable 3. (So now Thread 1 is running QRunnable 3, and Thread 2 running QRunnable 2).

    Do you want to associate your row with a thread number or QRunnable number?



  • [quote author="JKSH" date="1392173291"]A thread pool reuses the same thread to run many tasks.

    For example, suppose your pool has 2 threads (called Thread 1 and Thread 2), but you start 10 tasks.

    • Thread 1 runs Task 1, and Thread 2 runs Task 2. The other 8 tasks wait in the queue.
    • When Thread 1 finishes Task 1, it starts running Task 3. (So now Thread 1 is running Task 3, and Thread 2 running Task 2).

    Do you want to associate your row with a thread number or task number?[/quote]

    Forgive me for misunderstanding but the way I understand the thread/task design, there is one run method that has the same task for any threads that call it. So I am not sure what you mean by task number. Each row has the same task running in its own thread. The task is testing a piece of hardware connected to a USB hub and runs when the cable is inserted. During the course of the task each row will display either a pass or fail message within its row.

    To sum up then, I think its thread id per row though I assume the task number is a particular QRunnable


  • Moderators

    Hi,

    I've updated my previous post for clarity. By "task", I meant "instance of QRunnable". Even though each instance runs the same code, they are operating on a different piece of hardware (thus they are considered "different tasks"). Maybe "job" is a better word?

    @
    class Task : public QRunnable {
    Task(QStringList jobParams);
    ...
    };

    ...

    // Create and run 3 different jobs
    Task* job1 = new Task(params1);
    Task* job2 = new Task(params2);
    Task* job3 = new Task(params3);

    threadPool->start(job1);
    threadPool->start(job2);
    threadPool->start(job3);
    @

    [quote]Each row has the same task running in its own thread. The task is testing a piece of hardware connected to a USB hub and runs when the cable is inserted. During the course of the task each row will display either a pass or fail message within its row.[/quote]So it sounds like you want 1 row for each piece of hardware tested?

    One way is to record the hardware ID in the QRunnable when you start the test. Then, every time the QRunnable emits a signal, emit the ID as one of the signal parameters. The slot can then read the ID and choose the row to update.



  • OK,

    Let me provide some code here:
    Worker (QRunnable) class
    @
    class Worker : public QObject, public QRunnable
    {
    Q_OBJECT
    public:
    Worker();

    protected:
    virtual void run(void);
    };
    @

    Which is called when a windows message DBT_DEVICEARRIVAL get posted:
    @
    void MainWindow::TestThread(void)
    {
    worker = new Worker();
    worker->setAutoDelete(true);
    threadPool = QThreadPool::globalInstance();
    connect(worker, SIGNAL(StatusMessage(QString)), this, SLOT(DisplayStatusMessage(QString)), Qt::QueuedConnection);
    threadPool->start(worker);
    }
    @

    So each time a cable is plugged in, the GUI thread posts the device is attached and the TestThread method is called.

    The hardware has a USB device descriptor string such as
    @
    \?\usb#vid_0fe2&pid_0090#6&103465e1&0&1#{6e8eae90-55a8-4b3a-84db-7cec02ffe409}
    @ for example which displayed when the device is recognized by Windows Device Manager.

    The point is that the string for the hardware refers to the unit under test. I thought that the program needs to refer to the thread/task ID instead.


  • Moderators

    [quote author="astodolski" date="1392210834"]OK,

    Let me provide some code here:
    Worker (QRunnable) class
    @
    class Worker : public QObject, public QRunnable
    {
    Q_OBJECT
    public:
    Worker();

    protected:
    virtual void run(void);
    };
    @

    Which is called when a windows message DBT_DEVICEARRIVAL get posted:
    @
    void MainWindow::TestThread(void)
    {
    worker = new Worker();
    worker->setAutoDelete(true);
    threadPool = QThreadPool::globalInstance();
    connect(worker, SIGNAL(StatusMessage(QString)), this, SLOT(DisplayStatusMessage(QString)), Qt::QueuedConnection);
    threadPool->start(worker);
    }
    @

    So each time a cable is plugged in, the GUI thread posts the device is attached and the TestThread method is called.

    The hardware has a USB device descriptor string such as
    @
    \?\usb#vid_0fe2&pid_0090#6&103465e1&0&1#{6e8eae90-55a8-4b3a-84db-7cec02ffe409}
    @ for example which displayed when the device is recognized by Windows Device Manager.
    [/quote]Yep, all that looks good.

    [quote]The point is that the string for the hardware refers to the unit under test. I thought that the program needs to refer to the thread/task ID instead.[/quote]You don't HAVE to track anything. It's up to you to write the code to track whatever you want.

    Since the device descriptor is unique, you can map it to a row number, right?
    @
    MainWindow::DisplayStatusMessage(const QString& deviceDescriptor, const QString& message)
    {
    int rowNumber;

    if (deviceIsAlreadyKnown(deviceDescriptor))
        rowNumber = getDeviceRow(deviceDescriptor);
    
    else // New hardware
        rowNumber = assignANewRowNumber(deviceDescriptor);
    
    write(rowNumber, message);
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.