Inheriting QThread whitout calling start(), any problem ?



  • Hello All,

    I am wondering if there is any problem about creating a Object that inherits from QThread, but, sometimes I want to execute everything in the current Thread, in this case the QThread::start() is not called.

    I am developing a kind of Controller that will execute some external commands using QProcess, once the QProcess::start() is called everything happens according to QProcess signals and sometimes I do not create a new Thread for this.
    These commands can produce huge output and it is required to be parsed, this is the reason why sometimes I need a new Thread, but depending on the command it does not produce any output and in this case I do not need to create a new Thread, but I would like to have just one interface for both cases.

    This is my Class with some code:
    @
    class QProcessController : public QThread
    {
    Q_OBJECT

    protected: // abstract
    explicit QProcessController (QObject *parent=0);
    virtual ~QProcessController ();

    public:
    QProcess * addCommand(const QString& fullCommand);
    QProcess * addCommand(const QString& program, const QStringList &arguments);

    public slots:
    void startInNewThread(Priority priority = InheritPriority);
    void startInCurThread();
    void restart();

    protected: //reimplementation
    virtual void run();

    protected slots:
    virtual void slotProcessStarted();
    virtual void slotExtendedError (QProcess::ProcessError error);
    virtual void slotStdoutReady ();
    virtual void slotStderrReady ();

    protected slots: // pure methods
    virtual void slotProcessFinished (int retCode, QProcess::ExitStatus status)=0;

    private: // reimplement this to customize the QProcess stuff like setWorkingDirectory() and others
    virtual void customizeProcess(QProcess *) { }

    private:
    void privateRrun(bool newThread);
    void startNextProcess();
    };

    void QFProcessController::run()
    {
    BEGIN();
    SHOW_THREAD_ID() ;

    privateRrun(true);
    exec();
    
    END();
    

    }

    void QFProcessController::startInCurThread()
    {
    BEGIN();
    SHOW_THREAD_ID();
    //does not call QThread::start()
    this->privateRrun(false);
    END();
    }

    void QFProcessController::startInNewThread(Priority priority)
    {
    BEGIN();
    // it is necessary to do since object are being created outside the thread
    moveToThread(this);
    SHOW_THREAD_ID() ;
    QThread::start(priority);
    END();
    }

    @

    I will appreciate any comment.
    Thanks,
    Carlos


  • Moderators

    I think that you would probably be best served by making your worker code into its own class which is not subclassed from QThread. Then you have the ability to either use it unthreaded (as is) or threaded (by creating a standalone QThread and moving your worker object to that thread's context as described "here":/wiki/Threads_Events_QObjects in the wiki.)

    This is the preferred method of how QThreads should be utilized nowadays. This particular use case is good example of why.



  • First of all, yes, it's okay to create the QThread subclass, call some functions on it and delete it again, without ever actually starting the thread.

    However, you're using QThread wrong. QThread is not meant to be subclassed and especially you shouldn't move the thread itself to...itself (in startInNewThread).

    Create a QObject subclass which does your work, e.g. in the slot "doWork". If you have the situation where you don't need a thread, just don't create a QThread and just launch doWork on the object. If you indeed need a thread, do this:
    @QThread *thread = new QThread;
    workObject->moveToThread(thread);
    connect(thread, SIGNAL(started()), workObject, SLOT(doWork()));@
    for cleanup you might want to emit a "done" signal in your workObject that you connect to quit() and deleteLater() of the thread instance (and possibly also deleteLater your workObject). Then start the thread with thread->start();



  • DerManu,

    Thank you for the correction,

    I will implement a solution like in your suggestion.

    Just one doubt:

    Do you think that the workObject would be the current Object (this)? , becoming:
    @
    QThread *thread = new QThread;
    this->moveToThread(thread);
    connect(thread, SIGNAL(started()), this, SLOT(doWork()));
    @



  • Hm as long as QThread isn't owned by workObject it should be okay for the workObject to launch its thread and move itself there.
    I personally like it more when a third instance controls the thread and workObject creation and brings both together. This is helpful e.g. when you want to take the threads from a thread pool and feels slightly cleaner, because it keeps the achtual worker and the "low-level" thread handling separated.


Log in to reply
 

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