【发布时间】:2017-07-09 20:49:28
【问题描述】:
在mainwindow.ui 中,我创建了一个名为progressBar 的QProgressBar 和一个名为speckle 的QPushButton,这将启动繁重的计算。
在mainwindow.h 内部,我有一个合适的private slot 按钮和一个代表繁重计算的私有函数。 mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_speckle_clicked();
...
private:
Ui::MainWindow *ui;
QFutureWatcher<std::vector<cv::Mat>> futureWatcher;
std::vector<cv::Mat> progressSpecle();//heavy computation
};
futureWatcher 应该监视从QtConcurrent 返回的QFuture 对象:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
connect(&this->futureWatcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
...
}
...
void MainWindow::on_speckle_clicked()
{
//Start the computation.
QFuture<std::vector<cv::Mat>> future;
future = QtConcurrent::run(this, &MainWindow::progressSpecle);
this->futureWatcher.setFuture(future);
QThreadPool::globalInstance()->waitForDone();
vector<cv::Mat> result = future.result();
specklevisualization *s = new specklevisualization;
s-> setAttribute(Qt::WA_DeleteOnClose);
s-> start(result);
s-> show();
}
但应用程序不能那样工作。编译并单击 on speckle 后,mainwindow 没有响应。这是创建 x Threads 的 progressSpecle 成员函数:
void MainWindow::progressSpecle(){
vector<cv::Mat> input;
...//do something with input
vector<cv::Mat> result;
vector<cv::Mat> *all;
all = &result;
QThreadPool *threadPool = QThreadPool::globalInstance();
for(unsigned int i = 1; i<input.size(); i++) {
cv_speckle_algorithm *work = new cv_speckle_algorithm(input.at(i-1), input.at(i), all, i-1);
work->setAutoDelete(false);
threadPool->start(work);
}
while(true){
if(threadPool->activeThreadCount() == 1) return result;
}
}
应用程序正常工作,但 mainWindow 不负责,因为(我认为)while(true)。但我不明白为什么这会阻塞主窗口,因为整个progressSpecle 函数在一个单独的线程中工作,该线程以QtConcurrent 创建并开始。
为什么progressSpecle 函数会阻塞主窗口?
那么我怎样才能让progressBar 工作呢?
【问题讨论】:
-
有点跑题了,但是...如果
specklevisualization以任何方式从QWidget继承,那么您不能在非GUI 线程上创建它的实例。 -
@G.M.我已经更改了
progressSpecle函数,以便它返回result向量。 -
您是否在 MainWindow 构造函数之前创建了应用程序对象? QObject::connect() 是否将错误打印到控制台窗口?
-
@falk 你的意思是我在
MainWindow m; m.show();之前打电话给QApplication a(argc, argv);吗?好的。否QObject::connect()不会打印错误。为什么要呢?没有错误,但 mainWindow 没有响应......我更新了问题,以便清楚我遇到什么样的问题...... -
(大量编辑的)代码有几个明显的问题。
on_speckle_clicked在 GUI 线程上被调用,但在调用QThreadPool::waitForDone时被阻塞——这不起作用。此外,每个新创建的cv_speckle_algorithm都会传递一个对results的引用,暗示多个线程将同时写入results。这当然是个问题。我可以建议您一开始忘记QThreadPool,让基本算法以单线程方式工作,然后然后考虑使用`QThreadPool。
标签: c++ qt qthread qtconcurrent qprogressbar