I have a dialog which runs a time-consuming operation on its initialization. I wrapped this operation into an asynchronous function in order not to freeze the GUI.
Imagine a dialog/widget which shows the current weather fetched asynchronously from a remote server:
Dialog::Dialog()
{
auto label = new QLabel(this);
QtConcurrent::run([=]() {
const int temperature = getWeather(); // Time-consuming function
label->setText(temperature);
});
// The rest code, layouts initialization, etc.
}
If this dialog/widget is closed before the asynchronous operation is finished, the label->setText()
part will obviously lead to a crash because the widget object won't exist by that moment.
What is the proper way to deal such situations? Probably, I should use something else instead of QtConcurrent
(QThread
, for example) in order to properly cancel the asynchronous function when the dialog is closed.
Note that the actual code is about reading a bunch of files, not about networking, that's why using the async QNetworkRequest
interface is not a case.
// global or class member
QFutureWatcher<int> g_watcher;
Dialog::Dialog()
{
connect(&g_watcher, &QFutureWatcher<int>::finished, this, &Dialog::handleFinished);
QFuture<int> future = QtConcurrent::run([]() -> int
{
int temperature = getWeather(); // Time-consuming function
return temperature;
});
g_watcher.setFuture(future);
}
void Dialog::handleFinished()
{
// will never crash because will not be called when Dialog destroyed
ui->label->setText(QString::number(g_watcher.result()));
}
There is also possible to disconnect everything connected to the finished signal:
disconnect(&g_watcher, &QFutureWatcher<int>::finished, 0, 0);
p.s. As for cancel the async operation, it cannot be cancelled correctly by QtConcurrent
or QThread
methods.
There is QThread::terminate() method, but from the doc:
...Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path...
Therefore you have to implement some "cancel" flag inside your getWeather()
function, or do as written above.