2013-03-13 3 views
2

Платформа: Win7 x64, MinGW-rubenvb (4.7.2-x64), Qt 4.8Qt прекратить нити мицелия по QConcurrent :: бежать

Скажем, у меня есть несколько длинных задач (чтение файла населения, запись в файл населения, и запустить моделирование) порождало с использованием QConcurrent :: бежать, следующим образом:

void MainWindow::runLengthyJob() { 
    /* some setup */ 
    jobWatcher->setFuture(QConcurrent::run(theApp, &AppClass::lengthyJob)); 
    // lengthyJob - can be readPop(), writePop(), runSim() 
} 

Обычно эти задачи требуют не менее 15 секунд, чтобы закончить (для моделирования, она занимает более часа). Для предотвращения сбоев из пока еще не готовой резьбы, я заново осуществить MainWindow :: CloseEvent следующим образом:

void MainWindow::closeEvent(QCloseEvent *event) { 
    /* wait for any dangling thread */ 
    if (QThreadPool::globalInstance()->activeThreadCount()) 
     QThreadPool::globalInstance()->waitForDone(); 
    event->accept(); 
} // end: MainWindow::closeEvent 

Это работает хорошо, но когда я нажимаю на кнопку «х» MainWindow, кажется, замораживания и показывая «Не отвечая» (я думаю, текст предоставлен ОС), хотя он, наконец, прекратил приложение.

Я хочу выйти из приложения, как только закроется слот close() MainWindow. Итак, как я могу сократить время ожидания для еще не завершенных потоков? Или как я могу уведомить пользователя о том, что все еще выполняется длительная работа (что может занять несколько часов до полного закрытия)? (Я попытался включить QDialog/QMessagebox в closeEvent, но вновь созданные виджеты также замораживаются)

Примечание: для AppClass: lengthyJobs [readPop()/writePop()], это автономные функции, и я не могу сломать меньшие шаги. Для AppClass :: runSim() возможны меньшие шаги.

ответ

0

Прежде всего, будущее, возвращенное QtConcurrent :: run, не поддерживает отмену. Поэтому вы не можете просто отменить его. Лучшее, что вы можете сделать, это установить некоторый флаг в AppClass и проверить его в ваших длинныхJobs (как вы сказали, это возможно в случае runSim), а затем ждать завершения.

В любом случае, если вы хотите уведомить пользователя о выполняемой задаче, вы можете сделать следующее: создать подкласс QDialog, сказать WaitDialog с QTimer с некоторым периодом, запустить этот таймер при построении диалога, подключить сигнал таймаута() к некоторые слоты в этом диалоге, и принять диалог, если нет хода резьбы:

if (QThreadPool::globalInstance()->activeThreadCount() == 0) 
    accept(); 

, а затем в MainWindow :: CloseEvent:

void MainWindow::closeEvent(QCloseEvent *event) { 
    WaitDialog dlg; 
    dlg.exec(); 
    event->accept(); 
} 
+0

Если я подкласс QRunnable/QThread для выполнения задач, является возможным «отменить» потоки? –

+0

Если вы подклассифицируете QThread, вы можете использовать QThread :: terminate, хотя документация говорит, что это потенциально опасно, потому что при запуске потока не будет предоставлена ​​возможность выполнить какую-либо очистку. – user2155932

 Смежные вопросы

  • Нет связанных вопросов^_^