我正在运行异步任务,并希望在满足某个条件( 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
即可。
答案 0 :(得分:2)
据我所知,在C ++中没有优雅的方法来关闭线程/异步任务。
一种简单的方法是使用std::atomic<bool>
或std::atomic_flag
而不是互斥锁。
如果您熟悉boost库,那么可以将boost::thread
与interruption_points一起使用。
答案 1 :(得分:1)
我有一种解决方案可以解决这种问题。我使用std::mutex
,std::condition_variable
和std::unique_lock<std::mutex>
来创建两种方法:pauseThread
和resumeThread
。
这个想法是使用condition_variable
和unique_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)
使用毫秒。+
最后,如果您执行此示例,则可以得到如下输出: