c++ - QFuture 信号在错误的时间发出

标签 c++ windows multithreading qt

我正在尝试使用 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;
}

最佳答案

虽然文档中没有明确说明,QFutureWatcher::setFuture每当您获得新的 QFuture 时都必须调用来自 QtConcurrent::run() ,这意味着您不能调用 setFutureImageViewer 的构造函数中正如你所做的那样。此外,没有必要保留 QFuture。自QFutureWatcher起成为类(class)成员提供确定并发任务是否仍在运行的方法。

总而言之,从构造函数中删除这一行: 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;
}

关于c++ - QFuture 信号在错误的时间发出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28951580/

相关文章:

c++ - 你能在不使用数组的情况下将不同数量的相同类型的参数传递给函数吗?

Windows 8 应用商店应用程序、Type.IsClass 和 System.ComponentModel.DesignerProperties.IsInDesignTool 缺失

html - 源代码中出现类型为 ="application/npfido"的随机 html 标签

java - 如何恢复由于 linkedBlockingQueue.take() 而处于阻塞进程的线程

c++ - glm::dvec 的 '1.0f' 对于 glm::angleAxis 是什么意思?

c++ - 表达式中的隐式类型转换 int 到 double

c++ - 避免隐式转换

windows - 自解压自检可执行文件

c++ - 多线程程序仅适用于打印语句

multithreading - Parallel For-Each 与 Scatter Gather in mule