Qt UI线程问题

时间:2013-04-24 15:52:43

标签: c++ multithreading qt

好的,所以我已经问了几个关于QFuture的问题,这正是我目前用来线程化我的UI应用程序的。

基本上我在一个类中有一个函数,需要很长时间,所以我希望它有线程,所以当从我的UI类调用时它并没有锁定我的UI。

然后我实现了一个QFutureWatcher来等待finished()信号,此时它将启动另一个在新线程中花费很多时间的函数(但是这个函数正在为UI做事)。我使用相同的代码来实现第二个线程函数,但是这个仍然会锁定我的UI。

我得出了可能完全错误的结论,但我似乎无法找出为什么它不起作用所以我能做的就是假设并在这里问...

也许我不能使用QConcurrentRun

获得2个QFuture

不能将QFuture与ui的东西一起使用(在我的情况下,QGraphicsView添加到场景中)

如果有人提出了很好的建议,iv在另一篇文章中读到我应该可能是QObject的子类但没有给出示例,所以我无法真正实现这一点,因为我不知道我的意思是什么样的功能甚至是重新实现。

TLDR:如何实现UI的功能(添加到QGraphicsScene)

代码示例,这是需要很长时间的函数,因为我从不同的函数循环中调用此函数几十万次,需要大约30秒才能完成UI在哪个时间没有响应

void GUI::paintSomething(double x, double y)
{
    /// Decalre a QPen for Painting dots
    QPen pen;

    // set the pen colour
    pen.setColor(Qt::white);

    // Add ellipse at the x y position passed in
    scene->addEllipse(x, y, 1.5, 1.5, pen, QBrush(Qt::SolidPattern));
}

线程代码,绘制所有调用paintSomething的函数

*future2 = QtConcurrent::run(this, &GUI::paintAll);

// Set watcher to look at QFuture futre2
watcher2->setFuture(*future2);

2 个答案:

答案 0 :(得分:4)

首先从任何东西更新ui /创建ui元素,但是你的主线程是一个很大的禁忌。所以,甚至不要走那条路。

在工作线程和主线程之间进行通信, 在Qt中,您可以在连接跨线程信号< - >时使用Qt::QueuedConnection。槽。

您通常打算做的是在工作线程中进行计算,当您创建并向QGraphicsView添加元素时,发送一个包含所需相关信息的信号,Catch它在主线程中并相应地采取行动。

<强>更新

好的,如果你的呼叫任何“几十万次”,即使它是一个大约30秒的主线程中的单个函数调用,你的性能会有所损失。这正是它归结为什么。没有什么神奇的技巧可以解决这个问题,因为你受到的硬件限制以及从根本上在时钟周期中可以提供什么。

您需要的是以不同的方式解决您的问题。问问自己QGraphicsView正在渲染什么。

是否可以将某些内容缓存到图像中?

所有几十件物品都需要互动吗?

您还可以查看Qt附带的"Mandelbrot - Example"以查看是否处理了跨线程更新。

答案 1 :(得分:0)

虽然这是非常糟糕的做法 - 从工作线程中更新GUI线程并且你应该通过信号槽实现它,你仍然可以通过QMetaObject::invokeMethod()更新GUI

您必须在工作线程中运行每个函数,通过invokeMethod()更新GUI。例如 - 您的void GUI::paintSomething(double x, double y)必须在线程中调用,如下所示:

QMetaObject::invokeMethod(this,"paintSomething", Q_ARG(double,x), Q_ARG(double,y));

GUI会发现冻结,但这肯定不会提高你的表现。

i call this function from a different functions loop a few hundred thousand times

当我做类似的任务时 - 我没有在每次更新后更新GUI,只需几次(QElapsedTimer)并在QImage中完成所有绘画,在一些超时后重新绘制在QLabel上。希望这有帮助