Qt :线程(续)

有关线程,可以做的是:

在QThread子类添加信号。这是绝对安全的,并且也是正确的(前面我们已经详细介绍过,发送者的线程依附性没有关系)

不应该做的是:

调用moveToThread(this)函数

指定连接类型:这通常意味着你正在做错误的事情,比如将QThread控制接口与业务逻辑混杂在了一起(而这应该放在该线程的一个独立对象中)

在QThread子类添加槽函数:这意味着它们将在错误的线程被调用,也就是QThread对象所在线程,而不是QThread对象管理的线程。这又需要你指定连接类型或者调用moveToThread(this)函数

使用QThread::terminate()函数

不能做的是:

在线程还在运行时退出程序。使用QThread::wait()函数等待线程结束

在QThread对象所管理的线程仍在运行时就销毁该对象。如果你需要某种“自行销毁”的操作,你可以把finished()信号同deleteLater()槽连接起来

什么时候应该使用线程

WebKit 发起一次请求

从服务器响应获取一些数据

WebKit 利用到达的数据开始进行网页布局,阻塞事件循环

由于事件循环被阻塞,也就没有了可用的事件循环,于是操作系统接收了到达的数据,但是却不能从QNetworkAccessManager的 socket 读取

内核缓冲区被填满,传输速度变慢

由于QNetworkAccessManager和QNetworkReply都是QObject,所以它们都不是线程安全的,因此你不能将它们移动到另外的线程继续使用。因为它们可能同时有两个线程访问:你自己的和它们所在的线程,这是因为派发给它们的事件会由后面一个线程的事件循环发出,但你不能确定哪一线程是“后面一个”。

Qt 4.8 之后,QNetworkAccessManager默认会在一个独立的线程处理 HTTP 请求,所以导致 GUI 失去响应以及操作系统缓冲区过快填满的问题应该已经被解决了。

最好最简单的实现是使用定时器,比如QTimer,设置 1s 超时,然后将doWork()作为槽:

class Worker : public QObject
{
Q_OBJECT
public:
    Worker()
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(doWork()));
        timer.start(1000);
    }
private slots:
    void doWork()
    {
        /* ... */
    }
private:
    QTimer timer;
};

猜你喜欢

转载自blog.csdn.net/u013288800/article/details/81395819
今日推荐