![](/img/trans.png)
[英]Telling an std::thread to kill/stop itself when a condition is met
[英]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::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)
。
最后,如果執行此示例,您將獲得類似以下的輸出:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.