終止非同步任務

Ding-yixia發表於2024-07-06

在Qt中,終止由QtConcurrent啟動的非同步任務並非直接和簡單,因為這些任務可能在多個工作執行緒中執行。但是,你可以使用QFutureWatcher配合QFuture的一些特性來嘗試取消或中斷任務。下面是一種常見的做法:

首先,你需要建立一個QFutureWatcher物件來監視QFuture的狀態。然後,你可以連線QFutureWatcherfinished()訊號到一個槽函式,在該槽函式中你可以檢查任務是否應該被取消。此外,你還需要在你的任務函式中定期檢查一個全域性變數或原子標誌,以確定是否應該提前結束任務。

以下是一個示例程式碼片段,展示瞭如何嘗試取消由QtConcurrent::map啟動的任務:

#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QAtomicInt>

QAtomicInt shouldCancel(false);

void taskFunction(int value)
{
    // 在任務函式中定期檢查是否應取消任務
    while (!shouldCancel.loadAcquire()) {
        // 執行任務的程式碼...
        // ...
    }
}

int main()
{
    QList<int> list;
    list << 1 << 2 << 3 << 4 << 5;

    QFuture<void> future = QtConcurrent::map(list, &taskFunction);
    QFutureWatcher<void> watcher;
    watcher.setFuture(future);

    // 連線watcher的finished訊號,以便在任務完成後或取消後執行一些程式碼
    connect(&watcher, &QFutureWatcher<void>::finished, [] {
        if (shouldCancel.loadAcquire()) {
            qDebug() << "Task was cancelled.";
        } else {
            qDebug() << "Task completed successfully.";
        }
    });

    // 某處觸發任務取消
    shouldCancel.storeRelease(true);

    // 等待任務完成或取消
    watcher.waitForFinished();

    return 0;
}

請注意,這種方法並不能立即停止任務,因為任務可能在不同的執行緒中執行,而執行緒可能在檢查取消標記之間執行多條指令。因此,取消可能是非同步的,並且在所有任務例項中可能不會立即生效。此外,你可能需要根據具體的任務性質來調整taskFunction中的迴圈和檢查機制,以確保任務能夠在適當的時候響應取消請求。

總之,取消由QtConcurrent啟動的任務需要在任務函式中顯式地檢查取消標記,並且可能需要一些額外的同步機制來確保正確性和執行緒安全。

相關文章