我正在尝试使用QT的QFuture和QFutureWatcher来实现一个带有通知的工作线程,但是通知不是在正确的时间来的!
我从菜单处理程序中调用loadFile(QString),并期望负载发生在工作线程中,这就是所发生的事情。但是ibLoadFinished()在执行connect之后就会被调用,而不是在退出LoadFromDisk()之后。(磁盘访问在IBF构造函数中完成)。
我做错了什么?
ImageViewer.h:
class ImageViewer : public QMainWindow
{
Q_OBJECT
public:
static IBF* LoadFromDisk(const QString& filename);
private:
QFuture<IBF*> ibfLoadedFuture;
QFutureWatcher<IBF*> ibfLoadedFutureWatcher;
private slots:
//...
Q_SLOT void ibLoadFinished();
}ImageViewer.cpp:
ImageViewer::ImageViewer() : ibfLoadedFutureWatcher(this)
{
// ...
connect(&ibfLoadedFutureWatcher, SIGNAL(finished()), this, SLOT(ibLoadFinished()));
ibfLoadedFutureWatcher.setFuture(ibfLoadedFuture);
//...
}
bool ImageViewer::loadFile(const QString& filename)
{
if (ibfLoadedFuture.isRunning())
return false;
ibfLoadedFuture = QtConcurrent::run(LoadFromDisk, filename);
return true;
}
IBF* ImageViewer::LoadFromDisk(const QString &filename)
{
IBF* ibf = new IBF(filename);
return ibf;
}
void ImageViewer::ibLoadFinished()
{
IBF* ibf(ibfLoadedFuture);
process(*ibf);
delete ibf;
}发布于 2015-03-09 22:36:03
尽管在文档中没有明确声明,但是无论何时从QFutureWatcher::setFuture获得新的QFuture,都必须调用QtConcurrent::run(),这意味着不能像以前那样在ImageViewer构造函数中调用setFuture。此外,不应该将QFuture保留为类的成员,因为QFutureWatcher提供了确定并发任务是否仍在运行的方法。
总之,从构造函数中删除这一行:ibfLoadedFutureWatcher.setFuture(ibfLoadedFuture);
然后将loadFile的实现更改为:
bool ImageViewer::loadFile(const QString& filename)
{
if (ibfLoadedFutureWatcher.isRunning())
return false;
QFuture<IBF*> ibfLoadedFuture = QtConcurrent::run(LoadFromDisk, filename);
ibfLoadFutureWatcher.setFuture(ibfLoadedFuture);
return true;
}此外,还可以使用QFutureWatcher::result()从并发运行中获得结果。
void ImageViewer::ibLoadFinished()
{
IBF* ibf = ibfLoadedFutureWatcher.result();
process(*ibf);
delete ibf;
}https://stackoverflow.com/questions/28951580
复制相似问题