Need help with multithreading
-
Hi. I have a function which I want to call with few instances in several threads. I suppose to use something like that:
void MainWindow::btn_clicked () { for (int i = 0; i < 10; ++i) { // different parts computing in different threads Function(a,b); // thread 1 Function(b,c); // thread 2 // after tasks in all threads are done UpdateMap(); // update QGrapchicScene sleep(delay); // pause } }
But during cycle is proceeding GUI should not be frozen.
So, what is the best practice to do that? QThreads or QConcurrent or something else? -
Hi,
QtConcurrent sounds like a good choice. However, the UpdateMap function should be connected to a QFutureWatcher to only run once all operations are done.
Why the call to sleep ?
-
I need pause just to see updated map.
Well, I'm trying to find out how to use QtConcurrent right now, but there is no significant success. I try:future1 = new QFuture<void>; watcher1 = new QFutureWatcher<void>; future2 = new QFuture<void>; watcher2 = new QFutureWatcher<void>; connect(watcher1, SIGNAL(finished()), this, SLOT(S())); connect(watcher2, SIGNAL(finished()), this, SLOT(S())); size_t s = fieldSizeI / 2; for (size_t i = 0; i < 10; ++i) { *future1 = QtConcurrent::run(field, &Field::PerformIteration, 0, s); *future2 = QtConcurrent::run( field, &Field::PerformIteration, s, 2*s); watcher1->setFuture(*future1); watcher2->setFuture(*future2); } void MainWindow::S() { ++workCounter; if (workCounter == 2) { field->AdoptNewState(); UpdateMap(); workCounter = 0; } }
It seems I'am doing it absolutely wrong. And I can't find an appropriate example.
-
QFutureWatcher *watcher1 = new QFutureWatcher<void>; QFutureWatcher *watcher2 = new QFutureWatcher<void>; connect(watcher1, SIGNAL(finished()), this, SLOT(S())); connect(watcher2, SIGNAL(finished()), this, SLOT(S())); size_t s = fieldSizeI / 2; QFuture<void> future1 = QtConcurrent::run(field, &Field::PerformIteration, 0, s); QFuture<void> future2 = QtConcurrent::run( field, &Field::PerformIteration, s, 2*s); watcher1->setFuture(future1); watcher2->setFuture(future2); }
-
Thanks. I used your code to construct the thing below. It looks not so hot but work just how I need.
// call this function to start void MainWindow::on_btn_iter_clicked() { maxIter = 5; s = fieldSizeI / threadsAmount; NewIteration(); } void MainWindow::NewIteration() { std::vector<QFutureWatcher<void> *> watchers (threadsAmount); for (size_t i = 0; i < threadsAmount; ++i) { watchers[i] = new QFutureWatcher<void>; connect (watchers[i], SIGNAL (finished()), this, SLOT (S())); } typedef std::vector<QFuture<void> > futures (threadsAmount); for (size_t i = 0; i < threadsAmount; ++i) { futures[i] = QtConcurrent::run(field, &CA_Field::PerformIteration, i*s, (i+1)*s ); watchers[i]->setFuture(futures[i]); } } void MainWindow::S() { ++workCounter; if (workCounter == threadsAmount) { field->AdoptNewState(); workCounter = 0; (--maxIter != 0) ? NewIteration() : UpdateHexMap(); } }