QThread Class

The QThread class provides a platform-independent way to manage threads.

ps:QThread类提供了一种与平台无关的方式来管理线程。

A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

ps:QThread对象管理程序中的一个线程的控制。 QThreads开始在run()中执行。 默认情况下,run()通过调用exec()启动事件循环,并在线程中运行一个Qt事件循环。

You can use worker objects by moving them to the thread using QObject::moveToThread().

ps:您可以使用工作对象,通过使用QObject :: moveToThread()将它们移动到线程。

class Worker : public QObject
{
    Q_OBJECT
    QThread workerThread;

public slots:
    void doWork(const QString &parameter) {
        // ...
        emit resultReady(result);
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
        connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};
View Code

The code inside the Worker's slot would then execute in a separate thread. However, you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections.

ps:Worker的槽内的代码将在另外的线程中执行。然而,你可以在任何线程中将Worker的槽连接到任何对象的任何信号。 排队连接的机制,可以安全地跨不同线程连接信号和插槽。

Another way to make code run in a separate thread, is to subclass QThread and reimplement run(). For example:

ps:另一种使代码在另外的线程中运行的方法是子类化QThread并重新实现run()。 例如:

class WorkerThread : public QThread
{
    Q_OBJECT
    void run() {
        QString result;
        /* expensive or blocking operation  */
        emit resultReady(result);
    }
signals:
    void resultReady(const QString &s);
};

void MyObject::startWorkInAThread()
{
    WorkerThread *workerThread = new WorkerThread(this);
    connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
    connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
    workerThread->start();
}
View Code

In that example, the thread will exit after the run function has returned. There will not be any event loop running in the thread unless you call exec().

ps:在该示例中,线程将在运行函数返回后退出。 除非你调用exec(),否则线程中不会有任何事件循环。

It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.

ps:重要的是记住一个QThread实例存在实例化它的旧线程中,而不是在调用run()的新线程。 这意味着所有QThread的队列槽将在旧线程中执行。 因此,希望调用新线程中的槽的开发人员必须使用 worker-object方法; 新的槽不应该直接实现到子类QThread中。

When subclassing QThread, keep in mind that the constructor executes in the old thread while run() executes in the new thread. If a member variable is accessed from both functions, then the variable is accessed from two different threads. Check that it is safe to do so.

ps:当子类化QThread时,记住构造函数在旧线程中执行,而run()在新线程中执行。 如果从两个函数访问成员变量,则从两个不同的线程访问变量。 检查这样做是否安全。

Note: Care must be taken when interacting with objects across different threads. See Synchronizing Threads for details.

ps:注意:在与不同线程上的对象交互时必须小心。 有关详细信息,请参阅同步线程。

Managing threads 管理线程

QThread will notifiy you via a signal when the thread is started(), finished(), and terminated(), or you can use isFinished() and isRunning() to query the state of the thread.

ps:当线程的状态改变时QThread会通过信号进行通知,或者也可以自己检查线程的状态

You can stop the thread by calling exit() or quit(). In extreme cases, you may want to forcibly terminate() an executing thread. However, doing so is dangerous and discouraged. Please read the documentation for terminate() and setTerminationEnabled() for detailed information.

ps:通过调用exit() or quit()停止线程。在极端情况下,通过调用terminate()强制停止正在执行的线程。这样做是危险的,不建议这样做

From Qt 4.8 onwards, it is possible to deallocate objects that live in a thread that has just ended, by connecting the finished() signal to QObject::deleteLater().

ps:从Qt 4.8起,可以通过将finished()信号连接到QObject::deleteLater()来释放生存在刚刚结束的线程中的对象。

Use wait() to block the calling thread, until the other thread has finished execution (or until a specified time has passed).

ps:使用wait()来阻塞调用线程,直到另一个线程完成执行(或直到指定的时间过去)。

The static functions currentThreadId() and currentThread() return identifiers for the currently executing thread. The former returns a platform specific ID for the thread; the latter returns a QThread pointer.

ps:静态函数currentThreadId()和currentThread()返回当前正在执行的线程的标识符。 前者返回线程的平台特定ID; 后者返回一个QThread指针。

To choose the name that your thread will be given (as identified by the command ps -L on Linux, for example), you can call setObjectName() before starting the thread. If you don't call setObjectName(), the name given to your thread will be the class name of the runtime type of your thread object (for example, "RenderThread" in the case of the Mandelbrot Example, as that is the name of theQThread subclass). Note that this is currently not available with release builds on Windows.

ps:给你的线程选择一个名字(例如,在Linux上由命令ps -L标识),可以在启动线程之前调用setObjectName()。 如果你不调用setObjectName(),你的线程的名字将是你的线程对象的运行时类型的类名(例如,在Mandelbrot示例的情况下,“RenderThread”,因为它是 QThread子类)。 请注意,目前不能在Windows上使用发行版。

QThread also provides static, platform independent sleep functions: sleep(), msleep(), and usleep() allow full second, millisecond, and microsecond resolution respectively.

ps:QThread还提供了静态,平台独立的睡眠功能:sleep(),msleep()和usleep(),分别允许全秒,毫秒和微秒分辨率。

Note: wait() and the sleep() functions should be unnecessary in general, since Qt is an event-driven framework. Instead of wait(), consider listening for the finished() signal. Instead of the sleep() functions, consider using QTimer.

ps:注意:wait()和sleep()函数在一般情况下应该是不必要的,因为Qt是一个事件驱动的框架。

enum QThread::Priority

ConstantValueDescription
QThread::IdlePriority 0 scheduled only when no other threads are running.
QThread::LowestPriority 1 scheduled less often than LowPriority.
QThread::LowPriority 2 scheduled less often than NormalPriority.
QThread::NormalPriority 3 the default priority of the operating system.
QThread::HighPriority 4 scheduled more often than NormalPriority.
QThread::HighestPriority 5 scheduled more often than HighPriority.
QThread::TimeCriticalPriority 6 scheduled as often as possible.
QThread::InheritPriority 7 use the same priority as the creating thread. This is the default.

posted on 2017-03-10 12:55  ycy白语  阅读(225)  评论(0编辑  收藏  举报