Improve the QtConcurrent ImageScaling example
Provide execution context to QFuture continuations, instead of using QMetaObject::invokeMethod calls for running in the main thread. Change-Id: Ica7de19494065d677ffc94224781bfbe292b4f21 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
f8f955151a
commit
81ed78c293
@ -128,23 +128,29 @@
|
|||||||
|
|
||||||
Since the scaling may be computationally heavy, and we don't want to block the main
|
Since the scaling may be computationally heavy, and we don't want to block the main
|
||||||
thread, we pass the \c QtFuture::Launch::Async option, to launch the scaling step in
|
thread, we pass the \c QtFuture::Launch::Async option, to launch the scaling step in
|
||||||
a new thread.
|
a new thread. The \c scaled() method returns a list of the scaled images to the next
|
||||||
|
step, which takes care of showing images in the layout.
|
||||||
|
|
||||||
The \c scaled() method returns a list of the scaled images to the next step, which
|
Note that \c updateStatus() is called through QMetaObject::invokeMethod(),
|
||||||
takes care of showing images in the layout:
|
because it updates the UI and needs to be invoked from the main thread.
|
||||||
|
|
||||||
\dots
|
\dots
|
||||||
\snippet imagescaling/imagescaling.cpp 5
|
\snippet imagescaling/imagescaling.cpp 5
|
||||||
\dots
|
\dots
|
||||||
|
|
||||||
Note that showImages() needs to be invoked from the main thread, so we call it through
|
For the same reason \c showImages() also needs to be invoked from the main thread, so
|
||||||
QMetaObject::invokeMethod().
|
we pass \c this as a context to \c .then(). By default, \c .then() is launched in the
|
||||||
|
parent's thread, but if a context object is specified, it is launched in the context
|
||||||
|
object's thread.
|
||||||
|
|
||||||
Then we add cancellation and failure handlers:
|
Then we add cancellation and failure handlers:
|
||||||
|
|
||||||
\dots
|
\dots
|
||||||
\snippet imagescaling/imagescaling.cpp 6
|
\snippet imagescaling/imagescaling.cpp 6
|
||||||
|
|
||||||
|
We don't need to specify the context anymore, because \c .onCanceled() and the next
|
||||||
|
handlers will be launched in their parent's context.
|
||||||
|
|
||||||
The handler attached via the \c .onCanceled() method will be called if the user has
|
The handler attached via the \c .onCanceled() method will be called if the user has
|
||||||
pressed the \e "Cancel" button:
|
pressed the \e "Cancel" button:
|
||||||
|
|
||||||
|
@ -118,24 +118,24 @@ void Images::process()
|
|||||||
downloadFuture.then([this](auto) { cancelButton->setEnabled(false); })
|
downloadFuture.then([this](auto) { cancelButton->setEnabled(false); })
|
||||||
.then(QtFuture::Launch::Async,
|
.then(QtFuture::Launch::Async,
|
||||||
[this] {
|
[this] {
|
||||||
updateStatus(tr("Scaling..."));
|
QMetaObject::invokeMethod(this,
|
||||||
|
[this] { updateStatus(tr("Scaling...")); });
|
||||||
return scaled();
|
return scaled();
|
||||||
})
|
})
|
||||||
//! [4]
|
//! [4]
|
||||||
//! [5]
|
//! [5]
|
||||||
.then([this](const QList<QImage> &scaled) {
|
.then(this, [this](const QList<QImage> &scaled) {
|
||||||
QMetaObject::invokeMethod(this, [this, scaled] { showImages(scaled); });
|
showImages(scaled);
|
||||||
updateStatus(tr("Finished"));
|
updateStatus(tr("Finished"));
|
||||||
})
|
})
|
||||||
//! [5]
|
//! [5]
|
||||||
//! [6]
|
//! [6]
|
||||||
.onCanceled([this] { updateStatus(tr("Download has been canceled.")); })
|
.onCanceled([this] { updateStatus(tr("Download has been canceled.")); })
|
||||||
.onFailed([this](QNetworkReply::NetworkError error) {
|
.onFailed([this](QNetworkReply::NetworkError error) {
|
||||||
const auto msg = QString("Download finished with error: %1").arg(error);
|
updateStatus(tr("Download finished with error: %1").arg(error));
|
||||||
updateStatus(tr(msg.toStdString().c_str()));
|
|
||||||
|
|
||||||
// Abort all pending requests
|
// Abort all pending requests
|
||||||
QMetaObject::invokeMethod(this, &Images::abortDownload);
|
abortDownload();
|
||||||
})
|
})
|
||||||
.onFailed([this](const std::exception& ex) {
|
.onFailed([this](const std::exception& ex) {
|
||||||
updateStatus(tr(ex.what()));
|
updateStatus(tr(ex.what()));
|
||||||
@ -256,7 +256,7 @@ void Images::initLayout(qsizetype count)
|
|||||||
|
|
||||||
void Images::updateStatus(const QString &msg)
|
void Images::updateStatus(const QString &msg)
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(this, [this, msg] { statusBar->showMessage(msg); });
|
statusBar->showMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Images::abortDownload()
|
void Images::abortDownload()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user