QFuture Class
template <typename T> class QFutureQFuture 클래스는 비동기 계산의 결과를 나타냅니다. 더 보기...
| 헤더: | #include <QFuture> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
- 상속된 멤버를 포함한 모든 멤버 목록
- 사용 중단된 멤버
- QFuture 는 스레딩 클래스의 일부입니다.
참고: 이 클래스의 모든 함수는 다음 예외를 제외하고 스레드 안전합니다:
공개 유형
| class | const_iterator |
| ConstIterator |
공개 함수
| QFuture() | |
| QFuture(const QFuture<T> &other) | |
| ~QFuture() | |
| QFuture<T>::const_iterator | begin() const |
| void | cancel() |
(since 6.10) void | cancelChain() |
| QFuture<T>::const_iterator | constBegin() const |
| QFuture<T>::const_iterator | constEnd() const |
| QFuture<T>::const_iterator | end() const |
| bool | isCanceled() const |
| bool | isFinished() const |
| bool | isResultReadyAt(int index) const |
| bool | isRunning() const |
| bool | isStarted() const |
(since 6.0) bool | isSuspended() const |
(since 6.0) bool | isSuspending() const |
(since 6.0) bool | isValid() const |
(since 6.0) QFuture<T> | onCanceled(Function &&handler) |
(since 6.1) QFuture<T> | onCanceled(QObject *context, Function &&handler) |
(since 6.0) QFuture<T> | onFailed(Function &&handler) |
(since 6.1) QFuture<T> | onFailed(QObject *context, Function &&handler) |
| int | progressMaximum() const |
| int | progressMinimum() const |
| QString | progressText() const |
| int | progressValue() const |
| T | result() const |
| T | resultAt(int index) const |
| int | resultCount() const |
| QList<T> | results() const |
| void | resume() |
(since 6.0) void | setSuspended(bool suspend) |
(since 6.0) void | suspend() |
(since 6.0) T | takeResult() |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(Function &&function) |
(since 6.1) QFuture<QFuture<T>::ResultType<Function>> | then(QObject *context, Function &&function) |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(QThreadPool *pool, Function &&function) |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(QtFuture::Launch policy, Function &&function) |
(since 6.0) void | toggleSuspended() |
(since 6.4) QFuture<U> | unwrap() |
| void | waitForFinished() |
| QFuture<T> & | operator=(const QFuture<T> &other) |
상세 설명
QFuture는 템플릿 클래스로, 템플릿 매개변수 T 가 비동기 계산이 생성하는 결과의 유형을 지정합니다.
QFuture를 사용하면 나중에 준비될 하나 이상의 결과에 대해 스레드를 동기화할 수 있습니다. 결과는 기본 생성자, 복사 생성자 및 이동 생성자(있는 경우)를 갖는 모든 유형일 수 있습니다. result(), resultAt(), results() 및 takeResult() 함수를 호출할 때 결과가 준비되지 않은 경우, QFuture는 결과가 준비될 때까지 대기합니다. isResultReadyAt() 함수를 사용하여 결과가 준비되었는지 여부를 확인할 수 있습니다. 두 개 이상의 결과를 반환하는 QFuture 객체의 경우, resultCount() 함수는 연속된 결과의 개수를 반환합니다. 즉, 0부터 resultCount()까지 결과를 순회하는 것은 항상 안전합니다. takeResult()은 퓨처를 무효화하며, 이후 해당 퓨처의 결과(result 또는 results)에 접근하려는 모든 시도는 정의되지 않은 동작을 초래합니다. isValid()는 결과에 접근할 수 있는지 여부를 알려줍니다.
QFuture는 Java 스타일의 이터레이터 (QFutureIterator)와 STL 스타일의 이터레이터 (QFuture::const_iterator)를 제공합니다. 이러한 이터레이터를 사용하는 것도 future의 결과에 접근하는 또 다른 방법입니다.
한 비동기 계산의 결과를 다른 계산으로 전달해야 하는 경우, QFuture는 then()를 사용하여 여러 순차적 계산을 연결하는 편리한 방법을 제공합니다. onCanceled()는 QFuture가 취소될 때 호출될 핸들러를 추가하는 데 사용할 수 있습니다. 또한, onFailed()를 사용하여 체인에서 발생한 모든 오류를 처리할 수 있습니다. QFuture는 오류 처리를 위해 예외를 사용한다는 점에 유의하십시오. 예외를 사용할 수 없는 경우에도, 오류 유형을 QFuture 유형의 일부로 포함시켜 QFuture의 오류 상태를 나타낼 수 있습니다. 예를 들어, std::variant, std::any 또는 이와 유사한 유형을 사용하여 결과나 실패를 저장하거나, 사용자 정의 유형을 만들 수 있습니다.
아래 예제는 예외를 사용하지 않고 오류 처리를 수행하는 방법을 보여줍니다. 네트워크 위치에서 대용량 파일을 가져오기 위해 네트워크 요청을 보내고자 한다고 가정해 봅시다. 그런 다음, 성공 시 파일을 파일 시스템에 쓰고 해당 경로를 반환하고자 합니다. 이 두 작업 모두 서로 다른 오류로 인해 실패할 수 있습니다. 따라서 ` std::variant `를 사용하여 결과나 오류를 저장합니다:
using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>;
enum class IOError { FailedToRead, FailedToWrite };
using IOResult = std::variant<QString, IOError>;그리고 then()를 사용하여 두 작업을 결합합니다:
QFuture<IOResult> future = QtConcurrent::run([url] {
//...
return NetworkReply(QNetworkReply::TimeoutError);
}).then([](NetworkReply reply) {
if (auto error = std::get_if<QNetworkReply::NetworkError>(&reply))
return IOResult(IOError::FailedToRead);
auto data = std::get_if<QByteArray>(&reply);
// try to write *data and return IOError::FailedToWrite on failure
//...
});
auto result = future.result();
if (auto filePath = std::get_if<QString>(&result)) {
// do something with *filePath
}
else
{
// process the error
}여러 연속 처리(continuation)와 핸들러를 어떤 순서로든 연결할 수 있습니다. 예를 들어:
QFuture<int> testFuture = someIntFuture;
auto resultFuture = testFuture.then([](int res) {
// Block 1
}).onCanceled([] {
// Block 2
}).onFailed([] {
// Block 3
}).then([] {
// Block 4
}).onFailed([] {
// Block 5
}).onCanceled([] {
// Block 6
});testFuture 의 상태(취소됨, 예외 발생, 결과 있음)에 따라 다음 onCanceled(), onFailed() 또는 then()가 호출됩니다. 따라서 testFuture 가 성공적으로 수행되면 Block 1 가 호출됩니다. 이 역시 성공하면 다음 then() (Block 4)가 호출됩니다. testFuture 가 취소되거나 예외로 인해 실패할 경우, 각각 Block 2 또는 Block 3 가 호출됩니다. 그 후 다음 then()가 호출되며, 이 과정이 반복됩니다.
참고: Block 2 가 호출되어 예외가발생하면 , 뒤따르는 onFailed() (Block 3)에서 이를 처리합니다. 만약 onFailed()과 onCanceled()의 순서가 반대로 되어 있었다면, 예외 상태는 다음 연속으로 전파되어 결국 Block 5 에서 포착되었을 것입니다.
다음 예제에서는 첫 번째 onCanceled() (Block 2)이 제거되었습니다:
QFuture<int> testFuture = someIntFuture;
auto resultFuture = testFuture.then([](int res) {
// Block 1
}).onFailed([] {
// Block 3
}).then([] {
// Block 4
}).onFailed([] {
// Block 5
}).onCanceled([] {
// Block 6
});testFuture 가 취소되면, 그 상태가 다음 then()로 전파되며, 이 함수도 취소됩니다. 따라서 이 경우 Block 6 가 호출됩니다.
퓨처는 하나의 연속체만 가질 수 있습니다. 다음 예제를 살펴보겠습니다:
QPromise<int> p;
QFuture<int> f1 = p.future();
f1.then([](int) { qDebug("first"); });
QFuture<int> f2 = p.future();
f2.then([](int) { qDebug("second"); });
p.start();
p.addResult(42);
p.finish();이 경우 f1 와 f2 는 동일한 내부 상태를 공유하므로 사실상 동일한 QFuture 객체입니다. 결과적으로 f2 에 대해 then 를 호출하면 f1 에 지정된 연속체가 덮어쓰게 됩니다. 따라서 이 코드가 실행되면 "second" 만 출력됩니다.
QFuture는 실행 중인 계산과 상호작용할 수 있는 방법도 제공합니다. 예를 들어, cancel() 함수를 사용하여 계산을 취소할 수 있습니다. 계산을 일시 중지하거나 재개하려면 setSuspended() 함수나 suspend(), resume(), toggleSuspended() 편의 함수 중 하나를 사용하면 됩니다. 실행 중인 모든 비동기 계산이 취소되거나 일시 중지될 수 있는 것은 아니라는 점에 유의하십시오. 예를 들어, QtConcurrent::run()이 반환하는 퓨처는 취소할 수 없지만, QtConcurrent::mappedReduced()가 반환하는 퓨처는 취소할 수 있습니다.
진행 상황 정보는 progressValue(), progressMinimum(), progressMaximum() 및 progressText() 함수를 통해 제공됩니다. waitForFinished() 함수는 호출 스레드를 차단하고 계산이 완료될 때까지 대기하게 하여, 모든 결과를 확보할 수 있도록 합니다.
QFuture로 표현되는 계산의 상태는 isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending() 또는 isSuspended() 함수를 사용하여 조회할 수 있습니다.
QFuture<void>는 결과 가져오기 함수를 전혀 포함하지 않도록 특화되어 있습니다. 또한, 모든 QFuture<T>는 QFuture<void>에 할당되거나 복사될 수 있습니다. 이는 실제 결과 데이터가 아닌 상태나 진행 상황 정보만 필요한 경우에 유용합니다.
신호와 슬롯을 사용하여 실행 중인 태스크와 상호작용하려면 QFutureWatcher 를 사용하십시오.
또한 ` QtFuture::connect()`를 사용하여 신호를 QFuture 객체에 연결할 수 있으며, 이 객체는 신호가 발신될 때 해결됩니다. 이를 통해 QFuture 객체와 마찬가지로 신호를 다룰 수 있습니다. 예를 들어, ` then()`와 결합하면 신호에 여러 개의 연속 처리를 연결할 수 있으며, 이들은 동일한 스레드나 새로운 스레드에서 호출됩니다.
QtFuture::whenAll() 및 QtFuture::whenAny() 함수를 사용하면 여러 퓨처를 결합하고, 그중 마지막 또는 첫 번째가 완료되는 시점을 추적할 수 있습니다.
값을 가진 준비된 QFuture 객체나 예외를 보유한 QFuture 객체는 편의 함수인 QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture() 및 QtFuture::makeExceptionalFuture()을 사용하여 생성할 수 있습니다.
참고: 일부 API( QFuture::then() 또는 다양한 QtConcurrent 메서드 오버로드 참조)를 사용하면 특정 스레드 풀에서 계산을 예약할 수 있습니다. 그러나 QFuture는 교착 상태를 방지하고 스레드 사용을 최적화하기 위해 워크 스틸링(work-stealing) 알고리즘을 구현합니다. 그 결과, 계산은 QFuture의 결과를 요청한 스레드에서 직접 실행될 수 있습니다.
참고: 계산을 시작하고 결과를 QFuture에 저장하려면 QPromise 를 사용하거나 Qt Concurrent 프레임워크에 포함된 API 중 하나를 사용하십시오.
참조: QPromise, QtFuture::connect(), QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(), QtFuture::makeExceptionalFuture(), QFutureWatcher 및 Qt Concurrent.
멤버 함수 문서
QFuture::QFuture()
비어 있고 취소된 퓨처를 생성합니다.
QFuture::QFuture(const QFuture<T> &other)
other 의 복사본을 생성합니다.
operator=()도 참조하십시오 .
QFuture::~QFuture()
미래를 파괴합니다.
이 메서드는 비동기 계산을 대기하거나 취소하지 않는다는 점에 유의하십시오. 퓨처가 소멸되기 전에 계산이 완료되도록 보장해야 하는 경우 ` waitForFinished()` 또는 ` QFutureSynchronizer `을 사용하십시오.
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::begin() const
퓨처의 첫 번째 결과를 가리키는 const STL 스타일 이터레이터를 반환합니다.
constBegin() 및 end()도 참조하십시오 .
void QFuture::cancel()
이 퓨처가 나타내는 비동기 계산을 취소합니다. 취소 작업은 비동기적으로 수행된다는 점에 유의하십시오. 동기적인 취소가 필요한 경우, cancel()을 호출한 후 waitForFinished()를 사용하십시오.
취소된 퓨처에서도 현재 사용 가능한 결과에는 여전히 접근할 수 있지만, 이 함수를 호출한 후에는 새로운 결과가 제공되지 않습니다. 이 퓨처를 감시하고 있는 모든 QFutureWatcher 객체는 취소된 퓨처에 대해서는 진행 상황 및 결과 준비 신호를 전달하지 않습니다.
실행 중인 모든 비동기 계산이 취소될 수 있는 것은 아닙니다. 예를 들어, QtConcurrent::run()이 반환하는 퓨처는 취소할 수 없지만, QtConcurrent::mappedReduced()가 반환하는 퓨처는 취소할 수 있습니다.
cancelChain()도 참조하십시오 .
[since 6.10] void QFuture::cancelChain()
전체 연속 체인을 취소합니다. 이미 완료된 모든 퓨처는 변경되지 않으며, 그 결과는 여전히 사용할 수 있습니다. 진행 중인 모든 연속 처리는 취소되며, 연속 체인에 onCanceled() 핸들러가 존재할 경우 해당 핸들러가 호출됩니다.
auto f = QtConcurrent::run([] {/*...*/})
.then([]{
// Then 1
})
.then([]{
// Then 2
})
.onCanceled([]{
// OnCanceled 1
})
.then([]{
// Then 3
})
.then([]{
// Then 4
})
.onCanceled([]{
// OnCanceled 2
});
//...
f.cancelChain();이 예제에서, Then 2 연속 처리가 실행되기 전에 체인이 취소되면, OnCanceled 1 및 OnCanceled 2 취소 핸들러가 모두 호출됩니다.
Then 2 이후에, 그러나 Then 4 이전에 체인이 취소되면 OnCanceled 2 만 호출됩니다.
참고: 이미 완료된 퓨처에 대해 이 메서드를호출하면 아무런 효과가 없습니다. 위 예제에서 보여준 것처럼, 전체 연속체 체인을 나타내는 QFuture 객체에 이 메서드를 사용하는 것이 권장됩니다.
연쇄 내의 어떤 연속체라도 비동기 계산을 실행하고 이를 나타내는 QFuture 를 반환하는 경우, cancelChain() 호출은 해당 중첩된 계산이 시작된 후에는 그 안으로 전파되지 않습니다. 그 이유는 미래(future)가 외부 미래가 완료된 경우에만 연속체 체인에서 사용할 수 있게 되지만, 취소는 외부 미래와 중첩된 미래 모두 계산이 완료되기를 기다리고 있는 시점에 발생할 수도 있기 때문입니다. 이러한 경우, 중첩된 미래는 명시적으로 캡처하여 취소해야 합니다.
QFuture<void> nested;
auto f = createFuture()
.then([&]{
nested = runNestedComputation();
// do some other work
return nested;
})
.unwrap()
.then([]{
// other continuation
})
.onCanceled([]{
// handle cancellation
});
//...
f.cancelChain();
nested.cancel();이 예제에서, ` runNestedComputation() `가 이미 진행 중이라면 ` nested.cancel()`를 호출해야만 취소할 수 있습니다.
이 함수는 Qt 6.10에서 도입되었습니다.
cancel()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const
퓨처의 첫 번째 결과를 가리키는 STL 스타일의 const 이터레이터를 반환합니다.
begin() 및 constEnd()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const
미래의 마지막 결과 다음에 오는 가상의 결과를 가리키는 const STL 스타일의 반복자를 반환합니다.
constBegin() 및 end()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const
미래의 마지막 결과 다음에 오는 가상의 결과를 가리키는 STL 스타일의 const 이터레이터를 반환합니다.
begin() 및 constEnd()도 참조하십시오 .
bool QFuture::isCanceled() const
cancel() 함수를 사용하여 비동기 계산이 취소된 경우 true 를 반환하고, 그렇지 않은 경우 false 를 반환합니다.
이 함수가 true 를 반환하더라도 계산이 여전히 실행 중일 수 있다는 점에 유의하십시오. 자세한 내용은 cancel()을 참조하십시오.
bool QFuture::isFinished() const
이 퓨처가 나타내는 비동기 연산이 완료된 경우 ` true `을 반환하고, 그렇지 않은 경우 ` false`을 반환합니다.
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture::isResultReadyAt(int index) const
index 의 결과가 즉시 사용 가능한 경우 true 을 반환하고, 그렇지 않은 경우 false 을 반환합니다.
참고: 이 함수를호출할 때 , isValid()이 이 QFuture 에 대해 false 를 반환하는 경우 정의되지 않은 동작이 발생합니다. 이 QFuture 가 아직 시작되지 않은 경우, 정의되지 않은 동작을 방지하려면 이 함수를 호출하기 전에 waitForFinished()을 호출하십시오.
resultAt(), resultCount(), takeResult()도 참조하십시오 .
bool QFuture::isRunning() const
이 퓨처가 나타내는 비동기 계산이 현재 실행 중이면 ` true `를 반환하고, 그렇지 않으면 ` false`를 반환합니다.
bool QFuture::isStarted() const
이 퓨처가 나타내는 비동기 계산이 시작된 경우 ` true `를 반환하고, 그렇지 않은 경우 ` false`를 반환합니다.
[since 6.0] bool QFuture::isSuspended() const
비동기 계산의 일시 중지가 요청되었고, 해당 일시 중지가 유효한 경우(즉, 더 이상 결과나 진행 상황의 변화가 예상되지 않는 경우) true 를 반환합니다.
이 함수는 Qt 6.0에서 도입되었습니다.
setSuspended(), toggleSuspended() 및 isSuspending()도 참조하십시오 .
[since 6.0] bool QFuture::isSuspending() const
suspend() 함수를 통해 비동기 연산이 일시 중지되었지만, 작업은 아직 일시 중지되지 않았고 연산이 여전히 실행 중인 경우 true 을 반환합니다. 그 외의 경우에는 false 을 반환합니다.
일시 중지가 실제로 적용되었는지 확인하려면 대신 isSuspended()을 사용하십시오.
이 함수는 Qt 6.0에서 도입되었습니다.
setSuspended(), toggleSuspended(), isSuspended()도 참조하십시오 .
[since 6.0] bool QFuture::isValid() const
이 ` QFuture ` 객체에서 하나 이상의 결과를 액세스하거나 가져올 수 있는 경우 ` true `를 반환합니다. 관련 ` QPromise `가 아직 시작되지 않았거나 `Future`에서 결과가 이미 수집된 경우 ` false `를 반환합니다.
참고: 이 함수의 반환값은 future 결과가 소비될 수 있는지 여부만을 나타낼 뿐, 결과가 준비되었는지는 나타내지 않습니다. 이 함수는 관련 QPromise 가 시작되었으나 결과가 아직 준비되지 않은 경우에도 true 를 반환합니다. 준비 상태를 확인하려면 isResultReadyAt() 또는 isFinished()를 호출하십시오.
이 함수는 Qt 6.0에서 도입되었습니다.
takeResult(), result(), results(), resultAt(), isFinished(), isResultReadyAt()도 참조하십시오 .
[since 6.0] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(Function &&handler)
이 퓨처에 취소 핸들러 handler 를 연결합니다. 반환된 퓨처는 이 퓨처가 취소되지 않는 한, 이 퓨처와 정확히 동일하게 동작합니다(동일한 상태와 결과를 가집니다). handler 는 인수를 받지 않고, 이 퓨처가 패키징한 유형의 값을 반환하는 호출 가능 객체입니다. 취소 후, 반환된 퓨처는 handler 가 반환한 값을 패키징합니다.
취소 전에 연결된 경우, ` handler `는 취소 후 퓨처를 완료된 것으로 보고하는 것과 동일한 스레드에서 호출됩니다. 이 퓨처가 이미 취소된 후에 핸들러가 연결되면, ` onCanceled()`를 실행하는 스레드에서 즉시 호출됩니다. 따라서 핸들러는 자신이 어떤 스레드에서 실행될지에 대해 항상 가정할 수는 없습니다. 핸들러가 호출될 스레드를 제어하려면 컨텍스트 객체를 인수로 받는 오버로드를 사용하십시오.
다음 예제는 취소 핸들러를 연결하는 방법을 보여줍니다:
QFuture<int> testFuture /*...*/;
auto resultFuture = testFuture.then([](int res) {
// Block 1
//...
return 1;
}).then([](int res) {
// Block 2
//...
return 2;
}).onCanceled([] {
// Block 3
//...
return -1;
});testFuture 가 취소되면 Block 3 가 호출되며, resultFuture 의 결과로는 -1 가 반환됩니다. testFuture 와 달리, 이는 Canceled 상태가 아닙니다. 즉, 결과를 가져오거나 연속체를 연결하는 등의 작업을 수행할 수 있습니다.
또한, 연속체 체인이 실행 중인 동안에도 체인을 시작한 future를 통해 체인을 취소할 수 있다는 점에 유의하십시오. 예를 들어, Block 1 가 이미 실행 중인 상태에서 testFuture.cancel() 가 호출되었다고 가정해 봅시다. 다음 연속체는 취소 요청이 있었음을 감지하므로 Block 2 는 건너뛰고, 취소 핸들러(Block 3)가 호출됩니다.
참고: 이 메서드는 연속체 체인의 결과를 나타내는 새로운 QFuture 를 반환합니다. 결과로 생성된 QFuture 자체를 취소한다고 해서, 이를 생성한 연속체 체인 내의 취소 핸들러가 호출되지는 않습니다. 즉, resultFuture.cancel() 를 호출하더라도 Block 3 는 호출되지 않습니다. resultFuture 는 testFuture 에 취소 핸들러를 연결하여 생성된 퓨처이므로, resultFuture 자체에는 취소 핸들러가 연결되어 있지 않기 때문입니다. 오직 testFuture 의 취소나 onCancelled() 호출 이전에 연결된 연속체들이 반환한 퓨처들의 취소만이 Block 3 를 트리거할 수 있습니다.
이 함수는 Qt 6.0에서 도입되었습니다.
[since 6.1] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(QObject *context, Function &&handler)
이 퓨처에 취소 핸들러 handler 를 연결하여, 퓨처가 취소될 때 호출되도록 합니다. handler 는 인수를 받지 않는 호출 가능 객체입니다. 이 핸들러는 context 객체의 스레드에서 호출됩니다. 특정 스레드에서 취소를 처리해야 할 때 유용할 수 있습니다.
context 가 체인이 완료되기 전에 소멸되면, 해당 퓨처는 취소됩니다. 자세한 내용은 then()를 참조하십시오.
참고: 이 메서드를 호출할때는 체인 설정 과정에서 ` context `가 살아있는 상태를 유지해야 합니다.
handler 에 대한 자세한 내용은 다른 오버로드의 문서를 참조하십시오.
이 함수는 오버로드된 함수입니다.
이 함수는 Qt 6.1에서 도입되었습니다.
[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)
이 퓨처에 오류 핸들러를 연결하여 예외를 처리합니다. 반환된 퓨처는 이 퓨처가 예외로 인해 실패하지 않는 한, 이 퓨처와 정확히 동일하게 동작합니다(동일한 상태와 결과를 가집니다).
handler 는 인수를 전혀 받지 않거나, 특정 오류 유형을 필터링하기 위해 하나의 인수를 받는 호출 가능 객체이며, catch 문과 유사합니다. 이 함수는 해당 퓨처가 패키징한 유형의 값을 반환합니다. 오류 발생 후, 반환된 퓨처는 handler 에서 반환된 값을 패키징합니다.
핸들러는 예외가 발생했을 때만 호출됩니다. 이 핸들러가 연결된 후에 예외가 발생하면, 핸들러는 예외의 결과로 퓨처를 완료로 보고하는 스레드에서 실행됩니다. 이 퓨처가 이미 실패한 후에 핸들러가 연결되면, ` onFailed()`를 실행하는 스레드에서 핸들러가 즉시 호출됩니다. 따라서 핸들러는 자신이 어떤 스레드에서 실행될지 항상 가정할 수는 없습니다. 핸들러가 호출될 스레드를 제어하려면 컨텍스트 객체를 받는 오버로드를 사용하십시오.
다음 예제는 실패 핸들러를 연결하는 방법을 보여줍니다:
QFuture<int> future = someIntFuture;
auto resultFuture = future.then([](int res) {
//...
throw Error();
//...
return res;
}).onFailed([](const Error &e) {
// Handle exceptions of type Error
//...
return -1;
}).onFailed([] {
// Handle all other types of errors
//...
return -1;
});
auto result = resultFuture.result(); // result is -1여러 개의 핸들러가 연결된 경우, 발생된 예외 유형과 일치하는 첫 번째 핸들러가 호출됩니다. 예를 들어:
QFuture<int> future = someIntFuture;
future.then([](int res) {
//...
throw std::runtime_error("message");
//...
}).onFailed([](const std::exception &e) {
// This handler will be invoked
return -1;
}).onFailed([](const std::runtime_error &e) {
// This handler won't be invoked, because of the handler above.
return -1;
});어느 핸들러도 던져진 예외 유형과 일치하지 않는 경우, 예외는 결과 Future로 전파됩니다:
QFuture<int> future = someIntFuture;
auto resultFuture = future.then([](int res) {
//...
throw Error("message");
//...
return res;
}).onFailed([](const std::exception &e) {
// Won't be invoked
return -1;
}).onFailed([](const QException &e) {
// Won't be invoked
return -1;
});
try {
auto result = resultFuture.result();
} catch(QException &someException) {
// Handle the exception
}참고: 인수를 받지 않는 핸들러를 언제든지 연결하여 모든 예외 유형을 처리하고 try-catch 블록을 작성하지 않아도됩니다 .
이 함수는 Qt 6.0에서 도입되었습니다.
then() 및 onCanceled()도 참조하십시오 .
[since 6.1] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(QObject *context, Function &&handler)
이 퓨처에 실패 핸들러를 연결하여, 퓨처가 발생시키거나 이미 발생시킨 예외를 처리합니다. 이 퓨처와 동일한 유형의 QFuture 를 반환합니다. 이 핸들러는 예외가 발생한 경우에만, ` context ` 객체의 스레드에서 호출됩니다. 이는 오류를 특정 스레드에서 처리해야 할 때 유용할 수 있습니다. 예를 들어:
// somewhere in the main thread
auto future = QtConcurrent::run([] {
// This will run in a separate thread
//...
throw std::exception();
}).onFailed(this, [] {
// Update UI elements
});QtConcurrent::run 에 연결된 오류 핸들러는 UI 요소를 업데이트하며, GUI가 아닌 스레드에서는 호출될 수 없습니다. 따라서 .onFailed() 에 this 를 컨텍스트로 제공하여, 해당 핸들러가 메인 스레드에서 호출되도록 보장합니다.
체인 처리가 완료되기 전에 context 가 소멸되면 퓨처가 취소됩니다. 자세한 내용은 then()을 참조하십시오.
참고: 이 메서드를 호출할때는 체인 설정 동안 context 가 유지되도록 보장해야 합니다.
handler 에 대한 자세한 내용은 다른 오버로드의 문서를 참조하십시오.
이것은 오버로드된 함수입니다.
이 함수는 Qt 6.1에서 도입되었습니다.
then() 및 onCanceled()도 참조하십시오 .
int QFuture::progressMaximum() const
progressValue()의 최대값을 반환합니다.
progressValue() 및 progressMinimum()도 참조하십시오 .
int QFuture::progressMinimum() const
progressValue()의 최소값을 반환합니다.
progressValue() 및 progressMaximum()도 참조하십시오 .
QString QFuture::progressText() const
비동기 계산에서 보고된 진행 상황을 (선택 사항인) 텍스트 형식으로 반환합니다.
모든 계산이 진행 상황을 텍스트로 표현하는 것은 아니므로, 이 함수는 빈 문자열을 반환할 수도 있습니다.
int QFuture::progressValue() const
progressMinimum()과 progressMaximum() 사이의 현재 진행률 값을 반환합니다.
progressMinimum() 및 progressMaximum()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::result() const
미래에 반환될 첫 번째 결과를 반환합니다. 결과가 즉시 사용 가능하지 않은 경우, 이 함수는 차단되어 결과가 사용 가능해질 때까지 대기합니다. 이는 ` resultAt(0)`을 호출하기 위한 편의 메서드입니다. result() 는 내부적으로 저장된 결과의 복사본을 반환한다는 점에 유의하십시오. T 가 이동 전용(move-only) 유형이거나 결과를 복사하지 않으려는 경우, 대신 takeResult()을 사용하십시오.
참고: 이 함수를호출할 때 , isValid()가 이 QFuture 에 대해 false 를 반환하는 경우 정의되지 않은 동작이 발생합니다. 이 QFuture 가 아직 시작되지 않은 경우, 정의되지 않은 동작을 방지하기 위해 이 함수를 호출하기 전에 waitForFinished()를 호출하십시오.
resultAt(), results() 및 takeResult()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const
index 에 있는 결과를 나중에 반환합니다. 결과를 즉시 사용할 수 없는 경우, 이 함수는 블록 상태가 되어 결과가 사용 가능해질 때까지 대기합니다.
참고: 이 함수를호출할 때 , isValid()가 이 QFuture 에 대해 false 를 반환하면 정의되지 않은 동작이 발생합니다. 이 QFuture 가 아직 시작되지 않은 경우, 정의되지 않은 동작을 방지하려면 이 함수를 호출하기 전에 waitForFinished()를 호출하십시오.
result(), results(), takeResult(), resultCount()도 참조하십시오 .
int QFuture::resultCount() const
이 퓨처에서 사용할 수 있는 연속적인 결과의 개수를 반환합니다. 결과 집합에 공백이 있을 수 있으므로, 실제로 저장된 결과의 개수는 이 값과 다를 수 있습니다. 결과를 0부터 resultCount()까지 순차적으로 처리하는 것이 항상 안전합니다.
result(), resultAt(), results(), takeResult()도 참조하십시오 .
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> QFuture::results() const
퓨처의 모든 결과를 반환합니다. 결과를 즉시 사용할 수 없는 경우, 이 함수는 차단되어 결과가 사용 가능해질 때까지 대기합니다. results() 는 내부적으로 저장된 결과의 복사본을 반환한다는 점에 유의하십시오. 현재는 이동 전용(move-only) 유형 T 의 모든 결과를 가져오는 기능이 지원되지 않습니다. 하지만 STL 스타일의 반복자나 읽기 전용 Java 스타일의 반복자를 사용하여 이동 전용 결과 목록을 순회할 수는 있습니다.
참고: 이 함수를호출하면 , 이 QFuture 에 대해 isValid()이 false 를 반환하는 경우 정의되지 않은 동작이 발생합니다. 이 QFuture 이 아직 시작되지 않은 경우, 정의되지 않은 동작을 방지하려면 이 함수를 호출하기 전에 waitForFinished()를 호출하십시오.
result(), resultAt(), takeResult(), resultCount() 및 isValid()도 참조하십시오 .
void QFuture::resume()
future()로 표현된 비동기 계산을 재개합니다. 이는 단순히 setSuspended(false)를 호출하는 편의 메서드입니다.
suspend()도 참조하십시오 .
[since 6.0] void QFuture::setSuspended(bool suspend)
suspend 가 true인 경우, 이 함수는 future()가 나타내는 비동기 계산을 일시 중지합니다. 계산이 이미 일시 중지된 상태라면, 이 함수는 아무 작업도 수행하지 않습니다. future가 일시 중지되더라도 QFutureWatcher 는 진행 상황 및 결과 준비 신호의 전달을 즉시 중단하지 않습니다. 일시 중지 시점에도 여전히 진행 중이며 중지할 수 없는 계산이 남아 있을 수 있습니다. 이러한 계산에 대한 신호는 계속해서 전달됩니다.
suspend 가 false인 경우, 이 함수는 비동기 계산을 재개합니다. 계산이 이전에 일시 중지된 적이 없다면, 이 함수는 아무 작업도 수행하지 않습니다.
모든 계산이 일시 중지될 수 있는 것은 아니라는 점에 유의하십시오. 예를 들어, QtConcurrent::run()이 반환하는 QFuture 는 일시 중지할 수 없지만, QtConcurrent::mappedReduced()가 반환하는 QFuture 는 일시 중지할 수 있습니다.
이 함수는 Qt 6.0에서 도입되었습니다.
isSuspended(), suspend(), resume(), toggleSuspended()도 참조하십시오 .
[since 6.0] void QFuture::suspend()
이 퓨처가 나타내는 비동기 계산을 일시 중지합니다. 이는 단순히 ` setSuspended(true)`를 호출하는 편의 메서드입니다.
이 함수는 Qt 6.0에서 도입되었습니다.
resume()도 참조하십시오 .
[since 6.0] template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::takeResult()
isValid()가 true 를 반환할 때만 이 함수를 호출해야 하며, 그렇지 않은 경우 동작이 정의되지 않습니다. 이 함수는 QFuture 객체에서 첫 번째 결과를 가져옵니다(이동시퀀스). 다른 결과가 있는 경우, 첫 번째 결과를 가져온 후 나머지 결과는 버려집니다. 결과를 즉시 사용할 수 없는 경우, 이 함수는 차단되어 결과가 사용 가능해질 때까지 대기합니다. ` QFuture `는 가능한 경우 이동(move) 세미언틱을 사용하려고 시도하며, 유형이 이동 불가능한 경우 복사 생성(copy construction)으로 대체합니다. 결과가 가져온 후, ` isValid()`는 ` false`로 평가됩니다.
참고: 일반적으로` QFuture `은 서로 다른 ` QFuture ` 객체 간(그리고 잠재적으로 서로 다른 스레드 간)에 결과를 공유할 수 있도록 허용합니다. `takeResult()`는 ` QFuture `가 `move-only` 유형(예: `std::unique_ptr`)에서도 작동하도록 하기 위해 도입되었으므로, 단 하나의 스레드만이 퓨처에서 결과를 이동할 수 있으며, 이를 단 한 번만 수행한다고 가정합니다. 또한 현재로서는 모든 결과의 목록을 가져오는 기능은 지원되지 않는다는 점에 유의하십시오. 하지만 STL 스타일의 반복자나 읽기 전용 Java 스타일의 반복자를 사용하여 이동 전용 결과 목록을 순회할 수는 있습니다.
이 함수는 Qt 6.0에서 도입되었습니다.
result(), results(), resultAt(), isValid()도 참조하십시오 .
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)
이 퓨처에 연속체(continuation)를 연결하여, 필요에 따라 ‘ Sync ’ 정책을 사용하여 여러 비동기 연산을 연쇄적으로 수행할 수 있게 합니다. ` function `는 이 퓨처에 결과가 있는 경우(` QFuture`의 `<void>`가 아닌 경우), 해당 퓨처가 패키징한 유형의 인자를 받는 호출 가능 객체입니다. 그렇지 않은 경우 인수를 받지 않습니다. 이 메서드는 function 에서 반환된 유형의 값을 포장하는 새로운 QFuture 를 반환합니다. 반환된 퓨처는 연결된 연속체가 호출되거나, 이 퓨처가 실패하거나 취소될 때까지 초기화되지 않은 상태로 유지됩니다.
참고: 별도의 스레드에서 연속 처리를 시작해야 하는 경우, 이 메서드의 다른 오버로드를사용하십시오 .
다음과 같이 여러 연산을 연쇄적으로 호출할 수 있습니다:
QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...또는:
QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...연속체(continuation)는 (값 대신) 이전 퓨처를 나타내는 ` QFuture ` 인수를 받을 수도 있습니다. 이는 예를 들어 ` QFuture `에 여러 결과가 있고 사용자가 연속체 내에서 해당 결과에 접근하고자 할 때 유용할 수 있습니다. 또는 사용자가 여러 연속체의 체인을 중단하지 않기 위해 연속체 내에서 이전 퓨처의 예외를 처리해야 할 때도 유용합니다. 예를 들면 다음과 같습니다:
QFuture<int> future = someIntFuture;
future.then([](QFuture<int> f) {
try {
//...
auto result = f.result();
//...
} catch (QException &e) {
// handle the exception
}
}).then([](){/*...*/});경고: 이전 퓨처가 T 타입의 결과를 여러 개 포함하고 있으며, 연속체가 T 타입의 인수를 매개변수로 받는경우 , 이전 QFuture 에서 반환된 첫 번째 결과만 연속체 내에서 처리됩니다!
이전 퓨처에서 예외가 발생하고, 이 예외가 연속체 내부에서 처리되지 않으면, 호출자가 이를 처리할 수 있도록 예외가 연속체 퓨처로 전파됩니다:
QFuture<int> future = someIntFuture;
auto continuation = future.then([](int res1){ /*...*/ return res1; }).then([](int res2){ /*...*/ return res2; })/*...*/;
//...
// future throws an exception
try {
auto result = continuation.result();
} catch (QException &e) {
// handle the exception
}이 경우 연속 처리 체인 전체가 중단됩니다.
참고: 이 퓨처가취소되면 , 이에 연결된 연속체들도 함께 취소됩니다.
이 함수는 오버로드된 함수입니다.
이 함수는 Qt 6.0에서 도입되었습니다.
onFailed() 및 onCanceled()도 참조하십시오 .
[since 6.1] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QObject *context, Function &&function)
이 퓨처에 연속체(continuation)를 연결하여, 필요에 따라 여러 비동기 연산을 연쇄적으로 수행할 수 있게 합니다. 이 퓨처가 나타내는 비동기 연산이 완료되면, ` function `가 ` context ` 객체의 스레드에서 호출됩니다. 이는 연속체를 특정 스레드에서 호출해야 할 때 유용할 수 있습니다. 예를 들어:
// somewhere in the main thread
auto future = QtConcurrent::run([] {
// This will run in a separate thread
//...
}).then(this, [] {
// Update UI elements
});QtConcurrent::run 에 연결된 연속 함수는 UI 요소를 업데이트하므로, GUI가 아닌 스레드에서는 호출할 수 없습니다. 따라서 .then() 에 this 를 컨텍스트로 제공하여, 해당 함수가 메인 스레드에서 호출되도록 보장합니다.
다른 컨텍스트나 실행 정책이 명시되지 않는 한, 다음 연속체들도 동일한 컨텍스트에서 호출됩니다:
auto future = QtConcurrent::run([] {
//...
}).then(this, [] {
// Update UI elements
}).then([] {
// This will also run in the main thread
});이는 기본적으로 ` .then() `가 이전 함수와 동일한 스레드에서 호출되기 때문입니다.
하지만 이 퓨처가 이미 완료된 후에 연속체가 연결된 경우, 해당 연속체는 then() 를 실행하는 스레드에서 즉시 호출된다는 점에 유의하십시오:
QObject *context /*...*/;
auto future = cachedResultsReady ? QtFuture::makeReadyVoidFuture()
: QtConcurrent::run([] { /* compute result */});
auto continuation = future.then(context, [] {
// Runs in the context's thread
}).then([] {
// May or may not run in the context's thread
});위의 예에서 cachedResultsReady 가 true 이고, 준비된 퓨처가 반환된다면, 첫 번째 .then() 가 두 번째 가 연결되기 전에 완료될 가능성이 있습니다. 이 경우 현재 스레드에서 해결됩니다. 따라서 확실하지 않은 경우에는 컨텍스트를 명시적으로 전달하십시오.
context 가 체인이 완료되기 전에 소멸되면, 해당 future는 취소됩니다. 이는 context 가 더 이상 유효하지 않을 때 취소 핸들러가 호출될 수 있음을 의미합니다. 이를 방지하려면 context 를 QPointer 로 캡처하십시오:
QObject *context /*...*/;
QFuture<Result> future /*...*/;
auto continuation = future.then(context, [context](Result result) {
// ...
}).onCanceled([context = QPointer(context)] {
if (!context)
return; // context was destroyed already
// handle cancellation
});컨텍스트 객체가 소멸되면 즉시 취소가 발생합니다. 체인 내의 이전 퓨처들은 취소되지 않으며, 완료될 때까지 계속 실행됩니다.
참고: 이 메서드를 호출할때는 체인 설정 과정에서 ` context `가 살아있는 상태를 유지해야 합니다.
이 함수는 오버로드된 함수입니다.
이 함수는 Qt 6.1에서 도입되었습니다.
onFailed() 및 onCanceled()도 참조하십시오 .
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QThreadPool *pool, Function &&function)
이 퓨처에 연속 처리를 연결하여, 원하는 경우 여러 비동기 연산을 연쇄적으로 수행할 수 있게 합니다. 이 퓨처가 나타내는 비동기 연산이 완료되면, ` function `가 ` pool`에서 스케줄링됩니다.
이 함수는 오버로드된 함수입니다.
이 함수는 Qt 6.0에서 도입되었습니다.
onFailed() 및 onCanceled()도 참조하십시오 .
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QtFuture::Launch policy, Function &&function)
이 퓨처에 연속 처리를 연결하여, 여러 비동기 계산을 연쇄적으로 수행할 수 있게 합니다. 이 퓨처가 나타내는 비동기 계산이 완료되면, 지정된 실행 방식 policy 에 따라 ` function `가 호출됩니다. 연속 처리의 결과를 나타내는 새로운 ` QFuture `가 반환됩니다.
policy 에 따라, 연속 처리는 이 퓨처와 동일한 스레드에서 호출되거나, 새로운 스레드에서 호출되거나, 이 퓨처의 실행 정책 및 스레드 풀을 상속받게 됩니다. 실행 정책이 지정되지 않은 경우(호출 가능 객체만 받는 오버로드 참조), Sync 정책이 사용됩니다.
다음 예제에서는 두 연속체 모두 새로운 스레드(하지만 동일한 스레드 풀 내)에서 호출됩니다.
QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });다음 예제에서는 두 연속체 모두 동일한 스레드 풀을 사용하는 새로운 스레드에서 호출됩니다.
QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... })
.then(QtFuture::Launch::Inherit, [](int res2){ ... });function 에 대한 자세한 내용은 다른 오버로드의 문서를 참조하십시오.
이 함수는 오버로드된 함수입니다.
이 함수는 Qt 6.0에서 도입되었습니다.
onFailed() 및 onCanceled()도 참조하십시오 .
[since 6.0] void QFuture::toggleSuspended()
비동기 계산의 일시 중지 상태를 전환합니다. 즉, 계산이 현재 일시 중지 중이거나 일시 중지된 상태라면 이 함수를 호출하면 계산이 재개되고, 계산이 실행 중이라면 일시 중지됩니다. 이 함수는 ` setSuspended(!(isSuspending() || isSuspended()))`를 호출하기 위한 편의 메서드입니다.
이 함수는 Qt 6.0에서 도입되었습니다.
setSuspended(), suspend() 및 resume()도 참조하십시오 .
[since 6.4] template <typename U> QFuture<U> QFuture::unwrap()
이 ` QFuture<T>`에서 내부 퓨처를 풀어냅니다. 여기서 ` T `는 ` QFuture<U>` 유형의 퓨처이며, 즉 이 퓨처의 유형은 ` QFuture<QFuture<U>>`입니다. 예를 들어:
unwrappedFuture outerFuture 내에 중첩된 내부 Future가 완료되는 즉시 이 Future는 완료되며, 동일한 결과나 예외가 발생하고 내부 Future의 완료를 보고한 것과 동일한 스레드에서 처리됩니다. 내부 Future가 취소되면 도 함께 취소됩니다. unwrappedFuture
이는 여러 계산을 연쇄적으로 수행할 때, 그중 하나가 결과 유형으로 ` QFuture `를 반환하는 경우에 특히 유용합니다. 예를 들어, URL에서 여러 이미지를 다운로드하고, 이미지 크기를 조정한 다음, `QtConcurrent::mappedReduced()`를 사용하여 단일 이미지로 축소하고 싶다고 가정해 봅시다. 다음과 같이 작성할 수 있습니다:
auto downloadImages = [] (const QUrl &url) {
QList<QImage> images;
//...
return images;
};
auto processImages = [scale, reduceImages](const QList<QImage> &images) {
return QtConcurrent::mappedReduced(images, scale, reduceImages);
};
auto show = [](const QImage &image) { /*...*/ };
auto future = QtConcurrent::run(downloadImages, url)
.then(processImages)
.unwrap()
.then(show);여기서 ` QtConcurrent::mappedReduced() `는 ` QFuture<QImage>`를 반환하므로, ` .then(processImages) `는 ` QFuture<QFuture<QImage>>`를 반환합니다. ` show() `는 ` QImage `를 인수로 받기 때문에, ` .then(processImages) `의 결과를 직접 전달할 수 없습니다. 따라서 ` .unwrap()`를 호출해야 하는데, 이 함수는 내부 `future`의 결과가 준비되면 이를 가져와 다음 연속체(continuation)로 전달합니다.
중첩이 여러 번 이루어진 경우, .unwrap() 는 가장 안쪽 수준까지 내려갑니다:
이 함수는 Qt 6.4에서 도입되었습니다.
void QFuture::waitForFinished()
비동기 계산( cancel()로 실행된 계산 포함)이 완료될 때까지, 즉 isFinished()가 true 를 반환할 때까지 기다립니다.
QFuture<T> &QFuture::operator=(const QFuture<T> &other)
other 를 이 퓨처에 할당하고, 이 퓨처에 대한 참조를 반환합니다.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.