我正在编写一个路径跟踪器,并希望通过线程使其并行化。我有一个关于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]);
}
答案 0 :(得分:1)
更好的方法是使那些静态方法插槽并从QRunnable实例发出信号/将信号发送回QRunnable对象,如果你期望函数返回一些。
这将是线程安全的,您不需要传递/存储任何指针 - 因为通过传递/存储指针,您可能会遇到尝试访问已删除的对象的潜在风险。
您可以将指向PathTracer的指针传递给PTRunnable的构造函数,以便在需要时将所有信号和插槽连接到那里,但将指针存储为类成员将是一个糟糕的设计理念 - 无需存储它并存储它随着代码的增长,将来会出错。