我尝试使用QT的QFuture和QFutureWatcher来实现带有通知的工作线程,但通知未在正确的时间到来!
我从菜单处理程序调用{{1}},并期望在工作线程中发生加载,以及发生了什么。但loadFile(QString)
在执行ibLoadFinished()
之后立即被调用,而不是在退出之后
connect
。 (磁盘访问在IBF构造函数中完成。)
我做错了什么?
ImageViewer.h:
LoadFromDisk()
ImageViewer.cpp:
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();
}
答案 0 :(得分:2)
虽然文档中没有明确说明,但只要您从QFutureWatcher::setFuture
获得新的QFuture
,就必须调用QtConcurrent::run()
,这意味着您无法调用setFuture
在ImageViewer
的构造函数中,就像你所做的那样。此外,由于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;
}