mirror of https://github.com/qt/qtbase.git
159 lines
5.8 KiB
Plaintext
159 lines
5.8 KiB
Plaintext
// Copyright (C) 2020 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
|
|
|
/*!
|
|
\page qtconcurrenttask.html
|
|
\title Concurrent Task
|
|
\brief A configurable way to run a task in a separate thread.
|
|
\ingroup thread
|
|
|
|
QtConcurrent::task provides an alternative interface for running a
|
|
task in a separate thread. The return value of the function is made
|
|
available through the QFuture API.
|
|
|
|
If you want to just run a function in a separate thread without adjusting
|
|
any parameters, use QtConcurrent::run as that lets you write less code.
|
|
The QtConcurrent::task is designed for cases where you need to perform
|
|
extra configurations steps.
|
|
|
|
This function is a part of the \l {Qt Concurrent} framework.
|
|
|
|
\section1 Optimize includes
|
|
|
|
If you include the \c <QtConcurrent> header, the entire Qt Concurrent
|
|
module with the entire Qt Core module will be included, which may increase
|
|
compilation times and binary sizes. To use the
|
|
\l {QtConcurrent::task}{QtConcurrent::task()} function, you can include a
|
|
more specific header:
|
|
|
|
\code
|
|
#include <QtConcurrentTask>
|
|
\endcode
|
|
|
|
\section1 Fluent interface
|
|
|
|
The QtConcurrent::task returns an instance of an auxiliary class called
|
|
QtConcurrent::QTaskBuilder. Normally, you don't need to create an instance
|
|
of this class manually. The QtConcurrent::QTaskBuilder provides an interface
|
|
to adjust different task parameters in a chain-like manner. This approach
|
|
is known as a
|
|
\l {https://en.wikipedia.org/wiki/Fluent_interface}{fluent interface}.
|
|
|
|
You can just set the parameters you need and then kick a task off.
|
|
In order to finalize the configuration of a task you must invoke
|
|
QtConcurrent::QTaskBuilder::spawn. This function is non-blocking (i.e.
|
|
returns a future object immediately), but it's not guaranteed that the
|
|
task starts immediately. You can use the QFuture and QFutureWatcher classes
|
|
to monitor the status of the task.
|
|
|
|
See more examples and explanations below.
|
|
|
|
\section1 Running a task in a separate thread
|
|
|
|
To run a function in another thread, use QtConcurrent::QTaskBuilder::spawn:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 0
|
|
|
|
This will run a lambda function in a separate thread obtained from
|
|
the default QThreadPool.
|
|
|
|
\section1 Passing arguments to the task
|
|
|
|
Invoking a function with arguments is done by passing them to
|
|
QtConcurrent::QTaskBuilder::withArguments:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 1
|
|
|
|
A copy of each argument is made at the point where
|
|
QtConcurrent::QTaskBuilder::withArguments is called, and these values
|
|
are passed to the thread when it begins executing the task. Changes made
|
|
to the arguments after calling QtConcurrent::QTaskBuilder::withArguments
|
|
are not visible to the thread.
|
|
|
|
If you want to run a function that accepts arguments by reference, you
|
|
should use \l {https://en.cppreference.com/w/cpp/utility/functional/ref}
|
|
{std::ref/cref} auxiliary functions. These functions create thin wrappers
|
|
around passed arguments:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 2
|
|
|
|
Make sure that all wrapped objects live long enough. It is possible to
|
|
get undefined behavior if a task outlives the object wrapped by
|
|
std::ref/cref.
|
|
|
|
\section1 Returning values from the task
|
|
|
|
You can obtain the result of a task with the QFuture API:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 3
|
|
|
|
Note that QFuture::result() is a blocking call, it waits for the
|
|
result to become available. Use QFutureWatcher to get a notification
|
|
when the task has finished execution and the result is available.
|
|
|
|
In case you want to pass a result to another asynchronous task, you can
|
|
use QFuture::then() to create a chain of dependent tasks. See the QFuture
|
|
documentation for more details.
|
|
|
|
\section1 Additional API features
|
|
|
|
\section2 Using different types of callable objects
|
|
|
|
Strictly speaking, you can use any type of tasks and arguments that
|
|
satisfy the following condition:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 4
|
|
|
|
You can use a free function:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 5
|
|
|
|
You can use a member function:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 6
|
|
|
|
You can use a callable object with an operator():
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 7
|
|
|
|
If you want to use an existing callable object, you need to either
|
|
copy/move it to QtConcurrent::task or wrap it with std::ref/cref:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 8
|
|
|
|
\section2 Using custom thread pool
|
|
|
|
You can specify a custom thread pool:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 9
|
|
|
|
\section2 Setting priority for a task
|
|
|
|
You can set the priority for a task:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 10
|
|
|
|
If you don't need a future object, you can call
|
|
QtConcurrent::QTaskBuilder::spawn(QtConcurrent::FutureResult::Ignore):
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 11
|
|
|
|
You can access the promise object associated with the task by defining an
|
|
additional argument of \c {QPromise<T> &} type inside the function.
|
|
This additional argument must be the first argument passed to the function, and
|
|
like in \l {Concurrent Run With Promise} mode, the function is expected to return void type.
|
|
Result reporting is done through QPromise API:
|
|
|
|
\snippet code/src_concurrent_qtconcurrenttask.cpp 12
|
|
*/
|
|
|
|
/*!
|
|
\fn template <typename Task> [[nodiscard]] QTaskBuilder<Task> QtConcurrent::task(Task &&task);
|
|
\since 6.0
|
|
|
|
Creates an instance of QtConcurrent::QTaskBuilder. This object can be used
|
|
to adjust some parameters and run \a task in a separate thread.
|
|
|
|
\sa {Concurrent Task}, QtConcurrent::QTaskBuilder
|
|
*/
|