동시 실행
QtConcurrent::run() 함수는 별도의 스레드에서 함수를 실행합니다. 함수의 반환 값은 QFuture API를 통해 제공됩니다.
QtConcurrent::run()은 오버로드된 메서드입니다. 이러한 오버로드는 약간 다른 모드로 생각할 수 있습니다. 기본 모드에서 QtConcurrent::run()에 전달된 함수는 호출자에게 단일 계산 결과만 보고할 수 있습니다. 약속과 함께 실행 모드에서 QtConcurrent::run()에 전달된 함수는 추가 QPromise API를 사용하여 여러 결과 보고, 진행률 보고, 호출자의 요청에 따라 계산을 일시 중지하거나 호출자의 요청에 따라 계산을 중지할 수 있습니다.
이 함수는 Qt Concurrent 프레임워크의 일부입니다.
동시 실행(기본 모드)
QtConcurrent::run()에 전달된 함수는 그 반환값을 통해 결과를 보고할 수 있습니다.
별도의 스레드에서 함수 실행하기
다른 스레드에서 함수를 실행하려면 QtConcurrent::run()을 사용합니다:
extern void aFunction(); QFuture<void> future = QtConcurrent::run(aFunction);
그러면 기본 QThreadPool 에서 가져온 별도의 스레드에서 aFunction
이 실행됩니다. QFuture 및 QFutureWatcher 클래스를 사용하여 함수의 상태를 모니터링할 수 있습니다.
전용 스레드 풀을 사용하려면 QThreadPool 을 첫 번째 인수로 전달하면 됩니다:
extern void aFunction(); QThreadPool pool; QFuture<void> future = QtConcurrent::run(&pool, aFunction);
함수에 인수 전달하기
함수에 인수를 전달하려면 함수 이름 바로 뒤에 QtConcurrent::run() 호출에 인수를 추가하면 됩니다. 예를 들어
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string); int integer = ...; double floatingPoint = ...; QString string = ...; QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
각 인자의 복사본은 QtConcurrent::run()이 호출되는 지점에서 만들어지며, 이 값은 함수 실행을 시작할 때 스레드에 전달됩니다. QtConcurrent::run() 호출 후 인자에 대한 변경 사항은 스레드에 표시되지 않습니다.
QtConcurrent::run 은 오버로드된 함수를 직접 호출하는 것을 지원하지 않습니다. 예를 들어 아래 코드는 컴파일되지 않습니다:
void foo(int arg); void foo(int arg1, int arg2); ... QFuture<void> future = QtConcurrent::run(foo, 42);
가장 쉬운 해결 방법은 람다를 통해 오버로드된 함수를 호출하는 것입니다:
QFuture<void> future = QtConcurrent::run([] { foo(42); });
또는 static_cast
을 사용하여 컴파일러에 어떤 오버로드를 선택할지 알려줄 수 있습니다:
QFuture<void> future = QtConcurrent::run(static_cast<void(*)(int)>(foo), 42);
또는 qOverload:
QFuture<void> future = QtConcurrent::run(qOverload<int>(foo), 42);
함수에서 값 반환하기
함수의 모든 반환 값은 QFuture 을 통해 확인할 수 있습니다:
extern QString functionReturningAString(); QFuture<QString> future = QtConcurrent::run(functionReturningAString); ... QString result = future.result();
결과가 필요하지 않은 경우(예: 함수가 void
)를 반환하는 경우 함수 객체를 가져오는 QThreadPool::start() 오버로드를 사용하는 것이 더 효율적입니다.
위에 설명한 대로 인수를 전달하는 방법은 다음과 같습니다:
extern QString someFunction(const QByteArray &input); QByteArray bytearray = ...; QFuture<QString> future = QtConcurrent::run(someFunction, bytearray); ... QString result = future.result();
QFuture::result() 함수는 결과를 차단하고 결과를 사용할 수 있을 때까지 기다립니다. 함수가 실행을 완료하고 결과를 사용할 수 있게 되면 QFutureWatcher 을 사용하여 알림을 받습니다.
추가 API 기능
멤버 함수 사용
QtConcurrent::run()은 멤버 함수에 대한 포인터도 받아들입니다. 첫 번째 인자는 상수 참조나 클래스의 인스턴스에 대한 포인터여야 합니다. 상수 참조로 전달하는 것은 상수 멤버 함수를 호출할 때 유용하고, 포인터로 전달하는 것은 인스턴스를 수정하는 비상수 멤버 함수를 호출할 때 유용합니다.
예를 들어, 별도의 스레드에서 QByteArray::split()(const 멤버 함수)를 호출하는 것은 다음과 같이 수행됩니다:
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread QByteArray bytearray = "hello world"; QFuture<QList<QByteArray> > future = QtConcurrent::run(&QByteArray::split, bytearray, ' '); ... QList<QByteArray> result = future.result();
생성되지 않은 멤버 함수를 호출하는 것은 다음과 같이 수행됩니다:
// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread QImage image = ...; QFuture<void> future = QtConcurrent::run(&QImage::invertPixels, &image, QImage::InvertRgba); ... future.waitForFinished(); // At this point, the pixels in 'image' have been inverted
람다 함수 사용
람다 함수 호출은 다음과 같이 수행됩니다:
QFuture<void> future = QtConcurrent::run([=]() { // Code in this block will run in another thread }); ...
함수를 호출하면 참조로 전달된 객체를 수정하는 것은 다음과 같이 수행됩니다:
static void addOne(int &n) { ++n; } ... int n = 42; QtConcurrent::run(&addOne, std::ref(n)).waitForFinished(); // n == 43
호출 가능한 객체를 사용하는 것은 다음과 같이 수행됩니다:
struct TestClass { void operator()(int s1) { s = s1; } int s = 42; }; ... TestClass o; // Modify original object QtConcurrent::run(std::ref(o), 15).waitForFinished(); // o.s == 15 // Modify a copy of the original object QtConcurrent::run(o, 42).waitForFinished(); // o.s == 15 // Use a temporary object QtConcurrent::run(TestClass(), 42).waitForFinished(); // Ill-formed QtConcurrent::run(&o, 42).waitForFinished(); // compilation error
프로미스와 동시 실행
약속과 함께 실행 모드는 QtConcurrent::run()의 기본 모드에 비해 실행 중인 태스크를 더 많이 제어할 수 있게 해줍니다. 실행 중인 태스크의 진행 상황 보고, 여러 결과 보고, 요청이 있을 경우 실행 일시 중지, 호출자의 요청에 따른 태스크 취소 등이 가능합니다.
필수 QPromise 인자
Run With Promise 모드에서 QtConcurrent::run()에 전달되는 함수에는 QPromise<T> &
타입의 추가 인수가 있어야 하며, 여기서 T
은 계산 결과의 타입입니다(예: QtConcurrent::run()이 반환한 QFuture<T>의 T
타입과 일치해야 합니다):
extern void aFunction(QPromise<void> &promise); QFuture<void> future = QtConcurrent::run(aFunction);
promise
인수는 QtConcurrent::run() 함수 내에서 인스턴스화되고 그 참조는 호출된 aFunction
에 전달되므로 사용자는 이 모드에서 QtConcurrent::run()을 호출할 때 인스턴스화하거나 명시적으로 전달할 필요가 없습니다.
QPromise 유형의 추가 인수는 항상 함수의 인수 목록에 첫 번째 인자로 표시되어야 합니다:
extern void aFunction(QPromise<void> &promise, int arg1, const QString &arg2); int integer = ...; QString string = ...; QFuture<void> future = QtConcurrent::run(aFunction, integer, string);
결과 보고
QtConcurrent::run()의 기본 모드와 달리, Run With Promise 모드에서 QtConcurrent::run()에 전달된 함수는 항상 void 타입을 반환할 것으로 예상됩니다. 결과 보고는 QPromise 타입의 추가 인수를 통해 이루어집니다. 또한 다음과 같은 다중 결과 보고도 가능합니다:
void helloWorldFunction(QPromise<QString> &promise) { promise.addResult("Hello"); promise.addResult("world"); } QFuture<QString> future = QtConcurrent::run(helloWorldFunction); ... QList<QString> results = future.results();
참고: 일반적으로 QPromise 를 사용할 때처럼 계산의 시작과 끝을 나타내기 위해 QPromise::start() 및 QPromise::finish()를 호출할 필요가 없습니다. QtConcurrent::run()은 항상 실행을 시작하기 전과 완료한 후에 이들을 호출합니다.
실행 일시 중단 및 취소
QPromise API는 요청이 있을 경우 계산을 일시 중단 및 취소할 수도 있습니다:
void aFunction(QPromise<int> &promise) { for (int i = 0; i < 100; ++i) { promise.suspendIfRequested(); if (promise.isCanceled()) return; // computes the next result, may be time consuming like 1 second const int res = ... ; promise.addResult(res); } } QFuture<int> future = QtConcurrent::run(aFunction); ... // user pressed a pause button after 10 seconds future.suspend(); ... // user pressed a resume button after 10 seconds future.resume(); ... // user pressed a cancel button after 10 seconds future.cancel();
future.suspend()
호출은 실행 중인 작업의 실행을 보류하도록 요청합니다. 이 메서드를 호출한 후 실행 중인 작업은 반복 루프에서 다음 promise.suspendIfRequested()
호출 후 일시 중단됩니다. 이 경우 실행 중인 작업은 promise.suspendIfRequested()
로의 호출 시 차단됩니다. 차단된 호출은 future.resume()
이 호출된 후 차단이 해제됩니다. 내부적으로 suspendIfRequested()는 차단을 해제하기 위해 대기 조건을 사용하므로 호출자의 스레드에서 재개 요청이 왔는지 주기적으로 확인하기 위해 실행 중인 스레드는 차단 시 리소스를 낭비하는 대신 유휴 상태가 된다는 점에 유의하세요.
마지막 줄에서 future.cancel()
으로 호출하면 다음 promise.isCanceled()
으로의 호출은 true
을 반환하고 aFunction
은 추가 결과 보고 없이 즉시 반환됩니다.
참고: 취소 후 계산을 중지하기 위해 QPromise::finish()를 호출할 필요가 없습니다(일반적으로 QPromise)를 사용할 때처럼). QtConcurrent::run()은 항상 실행을 완료한 후에 호출합니다.
진행 상황 보고
결과 보고와 독립적으로 작업의 진행 상황을 보고하는 것도 가능합니다:
void aFunction(QPromise<int> &promise) { promise.setProgressRange(0, 100); int result = 0; for(int i = 0; i < 100; ++i) { // 작업의 일부분을 계산 const int part = ...; result += part; promise.setProgressValue(i); } promise.addResult(result); }QFutureWatcher<int> watcher;QObject::connect(&watcher, &.QFutureWatcher::progressValueChanged, [](int progress){ ...; // 진행 상황으로 GUI 업데이트 qDebug() << "current progress:" << progress; }); watcher.setFuture(QtConcurrent::run(aFunction));
호출자는 progressValueChanged()
신호에 연결하고 그에 따라 그래픽 사용자 인터페이스 등을 업데이트하기 위해 QtConcurrent::run()이 반환한 QFuture
에 대해 QFutureWatcher
을 설치합니다.
오버로드된 연산자()()로 함수 호출하기
기본적으로 QtConcurrent::run()은 약속과 함께 실행 모드에서 오버로드된 연산자()()가 있는 함수를 지원하지 않습니다. 오버로드된 함수의 경우 사용자는 다음과 같이 QtConcurrent::run()에 전달되는 템플릿 파라미터로 결과 유형을 명시적으로 지정해야 합니다:
© 2025 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.