如何防止在 Qt 中完成后台任务和 UI 之间的生命周期问题
How to prevent lifetime issues between completion of background task and UI in Qt
当使用QtConcurrent::run
到运行代码时,后台代码来自UI
QFuture::then(QObject *context, Function &&function)
可用于更新 UI,因为您可以将 window 对象作为上下文传递,以使 function
在 GUI 线程上执行。这很方便,但是有一个问题。当 window 关闭并在后台任务完成之前被释放时,程序将在任务完成时崩溃,因为传递给 then
的 context
不再有效。
有没有简单的方法来防止这个问题?我知道可以使用 QFutureWatcher
但该对象需要添加到 window class 并且 window 可以执行的每个异步任务都需要一个对象麻烦。
一个简单的选择是使用 QPointer
到 track/monitor 感兴趣的 QWidget
。 QPointer
的副本可以被 QtConcurrent::run
或 QFuture::then
使用的任何 lambda 或仿函数捕获。
/*
* Set up the QWidget that we need to monitor.
*/
auto w = std::make_unique<QLabel>("Working...");
w->show();
/*
* Create a QPointer that that we can use to check the validity of 'w'.
*/
auto qp = QPointer<QWidget>(w.get());
/*
* We can now bind qp into any lambdas.
*/
auto f = QtConcurrent::run(
[]
{
/* Time consuming stuff goes here. */
})
.then(
qApp,
[qp]
{
if (qp) {
/*
* qp reports that 'w' is still valid so do whatever we
* need to do with it.
*/
qp.data()->setText("Done");
} else {
/*
* 'w' is no longer valid.
*/
}
});
[注意:以上内容未经测试,因为我现在正在处理的盒子上没有 Qt6
。]
当使用QtConcurrent::run
到运行代码时,后台代码来自UI
QFuture::then(QObject *context, Function &&function)
可用于更新 UI,因为您可以将 window 对象作为上下文传递,以使 function
在 GUI 线程上执行。这很方便,但是有一个问题。当 window 关闭并在后台任务完成之前被释放时,程序将在任务完成时崩溃,因为传递给 then
的 context
不再有效。
有没有简单的方法来防止这个问题?我知道可以使用 QFutureWatcher
但该对象需要添加到 window class 并且 window 可以执行的每个异步任务都需要一个对象麻烦。
一个简单的选择是使用 QPointer
到 track/monitor 感兴趣的 QWidget
。 QPointer
的副本可以被 QtConcurrent::run
或 QFuture::then
使用的任何 lambda 或仿函数捕获。
/*
* Set up the QWidget that we need to monitor.
*/
auto w = std::make_unique<QLabel>("Working...");
w->show();
/*
* Create a QPointer that that we can use to check the validity of 'w'.
*/
auto qp = QPointer<QWidget>(w.get());
/*
* We can now bind qp into any lambdas.
*/
auto f = QtConcurrent::run(
[]
{
/* Time consuming stuff goes here. */
})
.then(
qApp,
[qp]
{
if (qp) {
/*
* qp reports that 'w' is still valid so do whatever we
* need to do with it.
*/
qp.data()->setText("Done");
} else {
/*
* 'w' is no longer valid.
*/
}
});
[注意:以上内容未经测试,因为我现在正在处理的盒子上没有 Qt6
。]