[英]How to cancel std::async when condition is met?
I am running an asynchronous task and want to cancel it when a certain condition ( bool ) 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();
}
Obviously, calling MyClass::cancelTask()
would cause a data-race, because this->CONDITION
is being written to and read from at the same time. 显然,调用
MyClass::cancelTask()
会导致数据争用,因为这是同时写入和读取此this->CONDITION
。 So the first thing that came to my mind is to use a std::mutex
. 因此,我想到的第一件事就是使用
std::mutex
。 However that would mean that the task has to lock and unlock the mutex on every new iteration of the while-loop. 但是,这意味着任务必须在while循环的每次新迭代中锁定和解锁互斥锁。 Since the async task is performance critical, this seems like a bad choice.
由于异步任务对性能至关重要,因此这似乎是一个错误的选择。
Is there a cleaner, and especially a more perfomant way to achieve what I am trying to do? 是否有更清洁的方法,尤其是更人性化的方法来实现我想要做的事情? Switching from
std::async
to std::thread
would be ok if it enabled an efficient solution. 如果启用了有效的解决方案,则可以从
std::async
切换到std::thread
。
As far as I know there is no elegant way to close a thread/async task in C++. 据我所知,没有一种优雅的方法可以关闭C ++中的线程/异步任务。
A simple way is to use std::atomic<bool>
or std::atomic_flag
instead of a mutex. 一种简单的方法是使用
std::atomic<bool>
或std::atomic_flag
而不是互斥锁。
If you are familiar with boost library, than you could use boost::thread
with interruption_points. 如果您熟悉boost库,则可以将
boost::thread
与interrupt_points一起使用。
I have a solution for this kind of requeirements. 对于这种要求,我有一个解决方案。 I use
std::mutex
, std::condition_variable
and std::unique_lock<std::mutex>
to create tow methods: pauseThread
and resumeThread
. 我使用
std::mutex
, std::condition_variable
和std::unique_lock<std::mutex>
创建两个方法: pauseThread
和resumeThread
。
The idea is use the condition_variable
and unique_lock
to make the thread wait for a time, for example 5 seconds, and after the time os over the thread continue its execution. 这个想法是使用
condition_variable
和unique_lock
使线程等待一段时间,例如5秒,然后在线程上的时间os之后继续执行它。 But, if you want to interrupt the condition_variable
you could use its method notify_one()
. 但是,如果要中断
condition_variable
,则可以使用其方法notify_one()
。
Using your code, and continue with your idea, i made some changes to your class: 使用您的代码,并继续您的想法,我对您的课程进行了一些更改:
MODIFICATION: I modify the flag bKeepRunning.
修改:我修改了标志bKeepRunning。
MyClass.h 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 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();
}
I made a console sample to show how it works: 我制作了一个控制台示例来演示其工作原理:
Main.cpp 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();
}
If you need some other period of time to pause your thread, you can try to change the interval and time of chrono::seconds(time)
to, for example, chrono::milliseconds(time)
that is using milliseconds.+ 如果您需要其他时间来暂停线程,则可以尝试将
chrono::seconds(time)
的间隔和时间更改为例如使用毫秒的chrono::milliseconds(time)
。
At the end, if you execute this sample, you could get an output like: 最后,如果执行此示例,您将获得类似以下的输出:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.