如何在满足条件时取消std :: async?

时间:2017-03-07 14:28:10

标签: c++ multithreading c++11 asynchronous

我正在运行异步任务,并希望在满足某个条件( 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即可。

2 个答案:

答案 0 :(得分:2)

据我所知,在C ++中没有优雅的方法来关闭线程/异步任务。

一种简单的方法是使用std::atomic<bool>std::atomic_flag而不是互斥锁。

如果您熟悉boost库,那么可以将boost::thread与interruption_points一起使用。

答案 1 :(得分:1)

我有一种解决方案可以解决这种问题。我使用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)使用毫秒。+

最后,如果您执行此示例,则可以得到如下输出:

enter image description here