我有一个对话框,它在初始化时运行耗时的操作。我将此操作包装到一个异步函数中,以免冻结GUI。
想象一个对话框/窗口小部件,它显示了从远程服务器异步获取的当前天气:
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.
}
如果在异步操作完成之前关闭此对话框/窗口小部件,则该label->setText()
部件显然会导致崩溃,因为此时微件对象将不存在。
处理此类情况的正确方法是什么?为了关闭对话框时正确取消异步功能,可能应该使用其他方式代替QtConcurrent
(QThread
例如)。
请注意,实际的代码是有关读取一堆文件的,而不是有关网络的,这就是为什么不使用异步QNetworkRequest
接口的原因。
// 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()));
}
也可以断开与完成信号连接的所有连接:
disconnect(&g_watcher, &QFutureWatcher<int>::finished, 0, 0);
ps至于取消异步操作,不能通过QtConcurrent
或QThread
方法正确取消它。
有QThread :: terminate()方法,但是来自doc:
...警告:此功能很危险,不建议使用。线程可以在其代码路径中的任何位置终止。
因此,您必须在getWeather()
函数内部实现一些“取消”标志,或者按照上面的描述进行操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句