Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtconcurrenttask.qdoc
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \page qtconcurrenttask.html
6 \title Concurrent Task
7 \brief A configurable way to run a task in a separate thread.
8 \ingroup thread
9
10 QtConcurrent::task provides an alternative interface for running a
11 task in a separate thread. The return value of the function is made
12 available through the QFuture API.
13
14 If you want to just run a function in a separate thread without adjusting
15 any parameters, use QtConcurrent::run as that lets you write less code.
16 The QtConcurrent::task is designed for cases where you need to perform
17 extra configurations steps.
18
19 This function is a part of the \l {Qt Concurrent} framework.
20
21 \section1 Fluent interface
22
23 The QtConcurrent::task returns an instance of an auxiliary class called
24 QtConcurrent::QTaskBuilder. Normally, you don't need to create an instance
25 of this class manually. The QtConcurrent::QTaskBuilder provides an interface
26 to adjust different task parameters in a chain-like manner. This approach
27 is known as a
28 \l {https://en.wikipedia.org/wiki/Fluent_interface}{fluent interface}.
29
30 You can just set the parameters you need and then kick a task off.
31 In order to finalize the configuration of a task you must invoke
32 QtConcurrent::QTaskBuilder::spawn. This function is non-blocking (i.e.
33 returns a future object immediately), but it's not guaranteed that the
34 task starts immediately. You can use the QFuture and QFutureWatcher classes
35 to monitor the status of the task.
36
37 See more examples and explanations below.
38
39 \section1 Running a task in a separate thread
40
41 To run a function in another thread, use QtConcurrent::QTaskBuilder::spawn:
42
43 \snippet code/src_concurrent_qtconcurrenttask.cpp 0
44
45 This will run a lambda function in a separate thread obtained from
46 the default QThreadPool.
47
48 \section1 Passing arguments to the task
49
50 Invoking a function with arguments is done by passing them to
51 QtConcurrent::QTaskBuilder::withArguments:
52
53 \snippet code/src_concurrent_qtconcurrenttask.cpp 1
54
55 A copy of each argument is made at the point where
56 QtConcurrent::QTaskBuilder::withArguments is called, and these values
57 are passed to the thread when it begins executing the task. Changes made
58 to the arguments after calling QtConcurrent::QTaskBuilder::withArguments
59 are not visible to the thread.
60
61 If you want to run a function that accepts arguments by reference, you
62 should use \l {https://en.cppreference.com/w/cpp/utility/functional/ref}
63 {std::ref/cref} auxiliary functions. These functions create thin wrappers
64 around passed arguments:
65
66 \snippet code/src_concurrent_qtconcurrenttask.cpp 2
67
68 Make sure that all wrapped objects live long enough. It is possible to
69 get undefined behavior if a task outlives the object wrapped by
70 std::ref/cref.
71
72 \section1 Returning values from the task
73
74 You can obtain the result of a task with the QFuture API:
75
76 \snippet code/src_concurrent_qtconcurrenttask.cpp 3
77
78 Note that QFuture::result() is a blocking call, it waits for the
79 result to become available. Use QFutureWatcher to get a notification
80 when the task has finished execution and the result is available.
81
82 In case you want to pass a result to another asynchronous task, you can
83 use QFuture::then() to create a chain of dependent tasks. See the QFuture
84 documentation for more details.
85
86 \section1 Additional API features
87
88 \section2 Using different types of callable objects
89
90 Strictly speaking, you can use any type of tasks and arguments that
91 satisfy the following condition:
92
93 \snippet code/src_concurrent_qtconcurrenttask.cpp 4
94
95 You can use a free function:
96
97 \snippet code/src_concurrent_qtconcurrenttask.cpp 5
98
99 You can use a member function:
100
101 \snippet code/src_concurrent_qtconcurrenttask.cpp 6
102
103 You can use a callable object with an operator():
104
105 \snippet code/src_concurrent_qtconcurrenttask.cpp 7
106
107 If you want to use an existing callable object, you need to either
108 copy/move it to QtConcurrent::task or wrap it with std::ref/cref:
109
110 \snippet code/src_concurrent_qtconcurrenttask.cpp 8
111
112 \section2 Using custom thread pool
113
114 You can specify a custom thread pool:
115
116 \snippet code/src_concurrent_qtconcurrenttask.cpp 9
117
118 \section2 Setting priority for a task
119
120 You can set the priority for a task:
121
122 \snippet code/src_concurrent_qtconcurrenttask.cpp 10
123
124 If you don't need a future object, you can call
125 QtConcurrent::QTaskBuilder::spawn(QtConcurrent::FutureResult::Ignore):
126
127 \snippet code/src_concurrent_qtconcurrenttask.cpp 11
128
129 You can access the promise object associated with the task by defining an
130 additional argument of \c {QPromise<T> &} type inside the function.
131 This additional argument must be the first argument passed to the function, and
132 like in \l {Concurrent Run With Promise} mode, the function is expected to return void type.
133 Result reporting is done through QPromise API:
134
135 \snippet code/src_concurrent_qtconcurrenttask.cpp 12
136*/
137
138/*!
139 \fn template <typename Task> [[nodiscard]] QTaskBuilder<Task> QtConcurrent::task(Task &&task);
140 \since 6.0
141
142 Creates an instance of QtConcurrent::QTaskBuilder. This object can be used
143 to adjust some parameters and run \a task in a separate thread.
144
145 \sa {Concurrent Task}, QtConcurrent::QTaskBuilder
146*/