Qt Worker线程 - 我必须为每个特定任务继承,还是可以使用回调?

时间:2016-01-21 15:59:58

标签: c++ multithreading qt

在Qt QThread使用的所有例子中,我都看到了同样的事情:

class MyThread : public QThread
{
/...
void run() { /...code
}
/...
};

因此,对于每个不同的任务,他们都会创建一个新课程。是否有一个特殊的原因,你不能有这个:

class GenericThraed : public QThread
{
/...
void run() { function();
}

FunctionCallback function; //Pointer to a function that you pass to the thread before starting its execution
/...
};

我的意思是它看起来更像是一种更好的选择,而且更加健壮。如果在线程运行之前设置了函数指针,那么应该没有任何问题,对吧?

2 个答案:

答案 0 :(得分:3)

QThread不是线程,但更像是线程控制器。

This article解释了如何真正使用QThreads。通常,您不需要继承QThread,特别是如果新线程需要事件循环。

您提出的方法的一个问题是它没有考虑在函数回调中访问的对象的线程亲和性。

例如: -

class SomeClass : public QObject
{
    Q_OBJECT

    public:
        void Increment() { m_index++; }

    private:
        int m_index = 0; // C++ 11 initialisation
};

现在,在主线程....

SomeClass * pMyObject = new SomeClass;

如果您在新线程中调用的函数有一个指向pMyObject的指针并调用其Increment函数,则可能会导致错误,因为该对象的线程关联性与主线程相关,而不是新线程。

所以,你可以将对象移动到新的QThread,但基本上,这就是我上面引用的文章所说的: -

QThread* pThread = new QThread;
pMyObject->moveToThread(pThread);

那么,functionCallback(?)的重点是什么,因为我们可以通过连接信号并启动线程来调用increment函数:

connect(pThread, &QThread::run, pMyObject, &SomeObject::Increment);
pThread->start();

或者通过从主线程调用方法

// object has been moved to another thread, but we can still call functions
// crossing the threads, by posting to the new thread's event queue
QMetaObject::invokeMethod(pMyObject, "increment", Qt::QueuedConnection);

在没有继承的情况下使用QThread的另一个好处是我们可以将多个QObject实例移动到类中,因此线程和对象之间不存在一对一的关系;毕竟,拥有比处理器内核更多的线程通常没什么好处。

虽然许多Qt的例子都可能继承自QThread,但在我看来,developers of QThread之一,并不总是最好的方法。

答案 1 :(得分:1)

是的,QThread缺少std::thread - 就像启动执行函数的线程一样。但是,它不一定更强大。例如,如果您需要事件循环,则无法在函数内调用exec()。 (请注意,如果您只需要一个作业队列QRunnable / QtConcurent::run可能更合适。