簡體   English   中英

滿足條件時如何取消std :: async?

[英]How to cancel std::async when condition is met?

我正在運行異步任務,想在滿足特定條件( bool )時取消它。

void MyClass::createTask()
{
    this->future = std::async(std::launch::async, [this](){
        while(this->CONDITION == false)
        {
            // do work
        }
    });
}

void MyClass::cancelTask()
{
    this->CONDITION = true;
    this->future.get();
}

顯然,調用MyClass::cancelTask()會導致數據爭用,因為這是同時寫入和讀取此this->CONDITION 因此,我想到的第一件事就是使用std::mutex 但是,這意味着任務必須在while循環的每次新迭代中鎖定和解鎖互斥鎖。 由於異步任務對性能至關重要,因此這似乎是一個錯誤的選擇。

是否有更清潔的方法,尤其是更人性化的方法來實現我想要做的事情? 如果啟用了有效的解決方案,則可以從std::async切換到std::thread

據我所知,沒有一種優雅的方法可以關閉C ++中的線程/異步任務。

一種簡單的方法是使用std::atomic<bool>std::atomic_flag而不是互斥鎖。

如果您熟悉boost庫,則可以將boost::thread與interrupt_points一起使用。

對於這種要求,我有一個解決方案。 我使用std::mutexstd::condition_variablestd::unique_lock<std::mutex>創建兩個方法: pauseThreadresumeThread

這個想法是使用condition_variableunique_lock使線程等待一段時間,例如5秒,然后在線程上的時間os之后繼續執行它。 但是,如果要中斷condition_variable ,則可以使用其方法notify_one()

使用您的代碼,並繼續您的想法,我對您的課程進行了一些更改:

修改:我修改了標志bKeepRunning。

MyClass.h

#include <mutex>
#include <chrono>
#include <future>
#include <atomic>

class MyClass
{
    std::atomic<bool> bKeepRunning;

    std::mutex mtx_t;
    std::condition_variable cv_t;
    std::future<void> _future;

public:
    MyClass();
    ~MyClass();

    void createTask();
    void stopTask();

    void pauseThread(int time);
    void resumeThread();

}

MyClass.cpp

#include "MyClass.h"

#include <iostream>

using namespace std;

MyClass::MyClass()
{
    bKeepRunning = false;
}

MyClass::~MyClass()
{
}

void MyClass::createTask()
{
    bKeepRunning = true;
    _future = std::async(std::launch::async, [this]() {
        int counter = 0;
        cout << "Thread running" << endl;
        while (bKeepRunning)
        {
            counter++;
            cout << "Asynchronous thread counter = [" << counter << "]" << endl;
            this->pauseThread(5);//Wait for 5 seconds
        }
        cout << "Thread finished." << endl;
    });
}

void MyClass::stopTask()
{
    cout << "Stoping Thread." << endl;
    bKeepRunning = false;
    resumeThread();
}

void MyClass::pauseThread(int time)
{
    std::unique_lock<std::mutex> lck_t(mtx_t);
    cv_t.wait_for(lck_t, chrono::seconds(time));
}

void MyClass::resumeThread()
{
    cout << "Resumming thread" << endl;
    cv_t.notify_one();
}

我制作了一個控制台示例來演示其工作原理:

Main.cpp的

#include <iostream>
#include <sstream>
#include <string>

#include "MyClass.h"

using namespace std;

int main(int argc, char* argv[])
{
    MyClass app;
    char line[80];

    cout << "Press Enter to stop thread." << endl;
    app.createTask();

    cin.getline(line,80);
    app.stopTask();
}

如果您需要其他時間來暫停線程,則可以嘗試將chrono::seconds(time)的間隔和時間更改為例如使用毫秒的chrono::milliseconds(time)

最后,如果執行此示例,您將獲得類似以下的輸出:

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM