이 페이지에서

병렬 실행

QtConcurrent::run() 함수는 별도의 스레드에서 함수를 실행합니다. 함수의 반환 값은 QFuture API를 통해 확인할 수 있습니다.

QtConcurrent::run()은 오버로드된 메서드입니다. 이러한 오버로드는 약간씩 다른 모드로 생각할 수 있습니다. 기본 모드에서는 QtConcurrent::run()에 전달된 함수가 호출자에게 단 하나의 계산 결과만 보고할 수 있습니다. '프로미스(promise)를 사용한 실행' 모드에서는 QtConcurrent::run()에 전달된 함수가 추가적인 QPromise API를 활용할 수 있으며, 이를 통해 여러 결과 보고, 진행 상황 보고, 호출자의 요청에 따른 계산 일시 중지 또는 호출자의 요구에 따른 계산 중지가 가능합니다.

이 함수는 Qt Concurrent 프레임워크의 일부입니다.

포함 파일 최적화

<QtConcurrent> 헤더를 포함하면 Qt Concurrent 모듈 전체와 Qt Core 모듈 전체가 함께 포함되므로, 컴파일 시간과 바이너리 크기가 증가할 수 있습니다. QtConcurrent::run() 함수를 사용하려면 더 구체적인 헤더를 포함할 수 있습니다:

#include <QtConcurrentRun>

동시 실행 (기본 모드)

QtConcurrent::run()에 전달된 함수는 반환 값을 통해 결과를 보고할 수 있습니다.

별도의 스레드에서 함수 실행

다른 스레드에서 함수를 실행하려면 QtConcurrent::run()을 사용합니다:

extern void aFunction();
QFuture<void> future = QtConcurrent::run(aFunction);

이렇게 하면 ` aFunction `가 기본 ` QThreadPool`에서 얻은 별도의 스레드에서 실행됩니다. ` 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()은 멤버 함수에 대한 포인터도 받아들입니다. Qt 6에서는 첫 번째 인자로 멤버 함수에 대한 포인터를 지정해야 하며, 그 다음으로 const 참조나 해당 클래스 인스턴스에 대한 포인터 중 하나를 지정해야 합니다. const 참조를 전달하는 것은 const 멤버 함수를 호출할 때 유용하며, 포인터를 전달하는 것은 인스턴스를 수정하는 non-const 멤버 함수를 호출할 때 유용합니다.

예를 들어, 별도의 스레드에서 ` 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();

const가 아닌 멤버 함수를 호출하는 방법은 다음과 같습니다:

// 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

프로미스를 이용한 동시 실행

'Run With Promise' 모드는 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::start() 및 QPromise::finish()을 호출할필요가 없습니다 ( QPromise 를 사용할 때 일반적으로 수행하는 것과 같이). 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()는 내부적으로 잠금 해제를 위해 wait 조건을 사용하므로, 실행 중인 스레드는 호출자 스레드로부터 재개 요청이 왔는지 주기적으로 확인하기 위해 차단된 상태에서 자원을 낭비하는 대신 유휴 상태로 전환됩니다.

마지막 줄의 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));

호출자는 QtConcurrent::run()이 반환한 ` QFuture `에 대해 ` QFutureWatcher `를 등록하여, 해당 ` `의 ` progressValueChanged() ` 신호에 연결하고, 이에 따라 예를 들어 그래픽 사용자 인터페이스를 업데이트합니다.

오버로드된 operator()()를 사용하여 함수 호출하기

기본적으로 QtConcurrent::run()은 ‘Run With Promise’ 모드에서 연산자()()가 오버로드된 펑크터를 지원하지 않습니다. 오버로드된 펑크터를 사용하는 경우, 사용자는 다음과 같이 QtConcurrent::run()에 전달되는 템플릿 매개변수로 결과 유형을 명시적으로 지정해야 합니다:

struct Functor {
    void operator()(QPromise<int> &) { }
    void operator()(QPromise<double> &) { }
};

Functor f;
run<double>(f); // this will select the 2nd overload
// run(f);      // error, both candidate overloads potentially match

© 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.