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

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

向QRunnable对象传递指向创建它们的类的指针是否合适,以便每个QRunnable都可以访问该类提供的静态方法(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实例发出信号/将信号发送回QRunnable对象,如果您希望从函数中返回一些信息。

这将是线程安全的,并且您将不需要传递/存储任何指针-因为通过传递/存储指针,您将面临尝试访问已删除对象的潜在风险。

您可以将指向PathTracer的指针传递给PTRunnable的构造函数,以在其中连接所有信号和插槽,但是将指针存储为类成员将是一个糟糕的设计思想-无需存储它,并且存储它将是错误的随着代码的增长,将来很容易出现。

10-06 09:40