QThreadPool & QRunnable & static function

QThreadPool & QRunnable & static functions

本文关键字:function static QRunnable QThreadPool      更新时间:2023-10-16

我正在编写一个路径跟踪器,并希望通过线程使其并行化。我有一个关于QT中多线程对象的设计问题,特别是关于QRunnable类。

在下面的(伪代码)中,我有一个类"PathTracer",它启动PTRunnable的实例,它扩展了QRunnable。

向QRunnable对象传递一个指向创建它们的类的指针,这样每个QRunnabble都可以访问该类提供的静态方法(doWork),这合适吗?我的理由是,如果出于某种原因我希望禁用多线程,PathTracer实例仍将在没有冗余的情况下实现必要的方法。

或者有更好的设计吗?私有实例变量m_data会发生什么情况?qrunnable对象是在共享的m_data上操作,还是会制作指针数据的副本?

#include <QThreadPool>
#include <vector>
class PathTracer
{
public:
    static void doWork(PathTracer * pt, Pixel pix);
protected:
    void renderImage();
    void modifyData();
private:
    int m_data;
};
PathTracer::renderImage()
{
    for (int x=0; x<width; x++)
    {
        for (int y=0; y<height; y++)
        {
            pixelblock.push_back(Pixel(x,y));
        }
    }
    // pass instance of self to each worker
    PTRunnable ptworker(this, pixelblock);
    QThreadPool::globalInstance()->start(ptworker);
};
void modifyData()
{
    m_data++;
}
static void PathTracer::doWork(PathTracer * pt, Point p)
{
    pt->modifyData();
}
//////////////////////////////
class PTRunnable : public QRunnable
{
    Q_OBJECT
public:
    explicit PTRunnable(QObject *parent = 0);
    PTRunnable(PathTracer * pt, PixelList pixels);
    void run(); // runnable implementation goes here
signals:
public slots:
private:
    PathTracer * m_pt; // owns pointer to pathtracer that spawned this
protected:
};

PTRunnable::PTRunnable(PathTracer * pt, PixelBlock block)
{
    m_pt = pt;
}
void PTRunnable::run()
{
    pt->doWork(this, block[0]);
}

更好的方法是让这些静态方法插入插槽,并从QRunnable实例发出信号/如果您希望函数返回一些信号,则将信号发送回QRunnabble对象。

这将是线程安全的,您不需要传递/存储任何指针,因为通过传递/存储指针,您会遇到试图访问已删除的obejct的潜在风险。

如果您愿意,可以将指向PathTracer的指针传递给PTRunnable的构造函数,以连接那里的所有信号和插槽,但将指针存储为类成员将是一个糟糕的设计想法-不需要存储它,而且随着代码的增长,存储它在未来很容易出错。