在使用Qt创建线程的时候突发奇想,竟然想把UI显示放到子线程中去,然后让主线程去处理业务逻辑,说干就干,于是qt就报出了以下错误来告诉我这样做不可以:

ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1145

目前我在项目中使用线程的场景:

1.线程生命周期和主进程生命周期相同,协同主进程去处理一些业务。

2.线程生命周期只在处理某个业务时用,其它时候不调用。

 

关于第一种创建线程的方式就不多说了,可以继承QThread,如果是在linux下也可以直接使用 pthread_create等。这里只简单说下qt的高级线程接口:QtConCurrent。

在QT5中,该API从core中移除,如果要引用该API需要在xxxx.pro文件中加入:

QT += concurrent

提到QtConcurrent就不得不说QFuture,关于QFuture官方文档是这样说的:

QFuture allows threads to be synchronized against one or more results which will be ready at a later point in time. The result can be of any type that has a default constructor and a copy constructor. If a result is not available at the time of calling the result(), resultAt(), or results() functions, QFuture will wait until the result becomes available. You can use the isResultReadyAt() function to determine if a result is ready or not. For QFuture objects that report more than one result, the resultCount() function returns the number of continuous results. This means that it is always safe to iterate through the results from 0 to resultCount().

大概就是:“QFuture允许线程对一个或多个结果进行同步”,了解到这里就差不多了,我们就使用它来做线程同步。

此处我使用它主要是后台要处理业务,而UI需要进行提示,当业务处理完毕时,要结束提示,返回主界面。如下图:

Qt线程之QtConCurrent_Qt之QtConcurrent

此处我对QFuture进行了简单的封装:

void WaitForUISync(const QFuture<void>& future)
{
    QEventLoop loop;
    QFutureWatcher<void> watcher;
    QObject::connect(&watcher,SIGNAL(finished()),&loop,SLOT(quit()));
    watcher.setFuture(future);
    loop.exec();
    return;
}

调用方式如下:

void run_thread_test(int &ret)
{
    for (int i=0; i < 50 ; i++) {
        DEBUG<<"current thread:"<<QThread::currentThread();
        QThread::usleep(1000 * 100);

    }
    ret = 0;

}

//如果是普通函数调用方式如下:
{
    int result = -1;
    QFuture<void> featrue =QtConcurrent::run(run_thread_test,&result );
    WaitForUISync(featrue);

}


void Widget::runThreadTest(int &ret)
{
    for (int i=0; i < 50 ; i++) {
        DEBUG<<"current thread:"<<QThread::currentThread();
        QThread::usleep(1000 * 100);

    }
    ret = 0;

}

//如果是类的成员函数,调用方式如下:
{
    int result = -1;
    QFuture<void> featrue =QtConcurrent::run(this , &Widget::runThreadTest,&result );
    WaitForUISync(featrue);
}