首先,我没有使用GUI。 (如果重要的话。)我想将文件的路径发送到一个线程(如char*
),让它处理文件,然后返回。最好,我希望线程在不使用时停止。
Qt文档显示了两种创建线程的方法:
创建QObject
和moveToThread()
。
在需要时创建QThread
然后start()
。
在上述两种方法中,如果我没有run()
功能,会发生什么?我没有,因为我没有看到将char*
传递给run()
的方法,所以我正在使用信号。我必须start()
线程才能正常工作吗?如果是这样,如果没有run()
,这会怎么做?我可以创建它,连接信号/插槽,然后在需要时调用它吗?在这种情况下,上述方法之一是否有优势?
更新:感谢您快速回复Johannes Schaub和thuga。
如果我正在使用QObject->moveToThread()
,那么该线程是否在事件循环中运行?当没有输入时,这个事件循环会休眠吗? (如果是这样,那很好。)线程(事件循环)与QObject
的信号和插槽相关联,对吧?所以我需要通过将它放在构造函数中将此对象的范围作为调用线程? (并且析构函数中有quit()
wait()
)它因此在原始线程的整个生命周期内运行?
我认为我不需要为QThread
设置一个插槽,因为我只想调用它,而不是来回通信。 (除了完成的信号。)所以我会做这样的事情:
一个。创建QThread
的实例:
WorkerThread *workerThread = new WorkerThread(this);
湾发送字符串。这是我不确定的部分。我想约翰内斯试图解释,但我还不清楚。我无法通过信号/插槽发送文件名,因为QThread
s不应使用插槽。 (但由于排队连接,可以在moveToThread()
情况下)
℃。使用.start()
答案 0 :(得分:3)
默认运行函数然后调用exec,它进入事件循环。如果循环没有要处理的事件,则循环休眠。
移动到该线程的对象不 QThread对象本身。这是另一个目标。 QThread对象本身只有事件循环,仍然与主线程关联(它的亲和力是主线程)。
如果线程在后台运行,最好使用QString作为文件名,然后调用相应的“processFile”函数或传递文件名的对象。调用可以通过信号槽连接或显式QMetaObject :: invokeMethod,使用连接类型QueuedConnection(将事件传递到对象线程的事件循环中,因此您的文件名通过包含在其中自动排队内部插槽调用事件)。
答案 1 :(得分:2)
如果我使用
QObject->moveToThread()
,那么该线程是否在事件循环中运行?
那些完全不相关。只要您QThread
,start()
只会运行事件循环。为此,您不需要将任何物体移动到它上面。当然事件循环处于休眠状态,因为它没有传入的事件要处理 - 所以线程尽管已经启动,但不会占用任何CPU。
线程(事件循环)与QObject的信号和插槽相关联,对吗?
信号和插槽只是您可以链接的功能呼叫源和接收器。它们与事件循环没什么关系。
当发送方和接收方对象驻留在不同的线程中时,通过将QMetaCallEvent
发布到对象的事件队列来实现插槽调用的传递。即使像所有事件一样,它也会被赋予QObject::event(QEvent*)
方法。该方法作用于QMetaCallEvent
并执行槽调用。
所以我需要将这个Object的作用域放在构造函数中作为调用线程吗? (并在析构函数中退出()wait())因此它在原始线程的整个生命周期内运行?
对象的生命周期与线程的生命周期分离。移动到给定线程的对象只能从该线程中被破坏。如果线程首先终止,则该对象变为无线程(其thread()
返回nullptr
),并且它可以从任何线程中被破坏,或者移动到另一个线程。无线程对象无法接收任何事件,但当然它可以接收直接的插槽调用。排队的老虎机呼叫不会起作用,因为它们最初作为事件传递,并且只在内部转换为呼叫。
我认为我不需要为QThread设置一个插槽,因为我只想调用它,而不是来回通信。
QThread
是一个线程控制器。没有理由将其子类化。几乎在所有情况下,您都可以使用已移至该主题的QObject
或QtConcurrent::run
。
所以我会做这样的事情:[...]创建QThread的实例:[...]发送字符串。
您希望将字符串发送到线程中的对象,而不是线程本身。
这是一个小例子:
// main.cpp
#include <QThread>
#include <QCoreApplication>
#include <QDebug>
class Worker : public QObject {
public:
Q_SLOT void say(const QString & str) { qDebug() << str; }
};
/// A thread that's safe to destruct at any time.
class Thread : public QThred {
using QThread::run;
public:
~QThread() { quit(); wait(); }
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
Worker worker;
Thread thread;
thread.start();
worker.moveToThread(&thread);
// Equivalent to invoking the say slot from a signal
QMetaObject::invokeMethod(&worker, "say", Q_ARG(QString, "hello"));
//
QMetaObject::invokeMethod(&app, "quit");
return app.exec();
}
#include "main.moc"
答案 2 :(得分:1)
听起来你的线程应该处理char*
然后等待。如果是这种情况,那么您可以使用第三个选项,在单个线程中运行单个函数,然后使用QtConcurrent::run()
退出
简单示例:
void workerFunction(QString const &data){
// ...
}
void callingFunction(){
// ....
char *data = .....;
QFuture<void> future = QtConcurrent::run(workerFunction, QString(data));
}
编辑:
如果您需要的功能多于单个线程函数,但不如QThread
的完全成熟子类那么多,那么QRunnable
/ QThreadPool
对也是一个方便的中间选项。< / p>