【C++】线程取消

#include <iostream>
#include <thread>
#include <syncstream> 
#include <vector>
#include <future>

int func(int id, std::stop_token token)
{
	int ret = -1;
	for (int ii = 0; ii < 50; ii++)
	{
		if (token.stop_requested())
		{
			return ret;	//返回线程取消时的ret
		}
		ret = ii;
		std::osyncstream(std::cout) << "[id]=" << id << ",ret=" << ret << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
	return ret;	//正常执行完时返回值
}

int main(int argc, char** argv)
{
	std::stop_source sts;
	std::vector<std::jthread> ths;	//工作线程
	std::vector<std::future<int>> tasks;	//工作线程执行结果
	for (int thid = 0; thid < 10; thid++)
	{
		std::packaged_task<int(int, std::stop_token)> task(func);
		auto ft = task.get_future();
		tasks.push_back(std::move(ft));
		ths.emplace_back(std::move(task), thid, sts.get_token());
	}

	// 注册回调
	// stop_source::request_stop()被调用时,线程被取消,callback触发调用
	// 捕获列表需引用捕获,因jthread和future不可拷贝
	std::stop_callback callback(sts.get_token(), [&ths, &tasks] {
		for (int thid = 0; thid < 10; thid++)
		{
			if (tasks.at(thid).wait_for(std::chrono::milliseconds(1000)) == std::future_status::ready)
			{
				auto& fttmp = tasks.at(thid);	//std::future不可拷贝,只能使用引用或指针
				auto& thtmp = ths.at(thid);		//std::thread不可拷贝
				std::cout << "[id]=" << thid <<",[tid] = " << thtmp.get_id() << ",has canceled..,ret = " << fttmp.get() << std::endl;
			}
		}
		});


	//方法1:指定时间内存在线程没执行完,取消所有线程
	int durationSec = 30;//指定全局的超时时间(s)
	std::vector<std::future<std::future_status>> fss;//所有工作线程在durationSec时间段后的执行状态
	std::atomic_bool allFinish(true);	//是否所有线程均执行完毕
	//因wait_for()会阻塞,为了同时判断各个工作线程是否执行完毕,创建和工作线程相同个数的【状态判断线程】,并行判定工作线程执行状态
	for (int thid = 0; thid < 10; thid++)
	{
		std::future<std::future_status> fs = std::async(std::launch::async, [&tasks,thid, durationSec]() {
				return tasks.at(thid).wait_for(std::chrono::seconds(durationSec));
			});
			
		fss.push_back(std::move(fs));
	}
	for (int thid = 0; thid < 10; thid++)
	{
		if (fss.at(thid).get() != std::future_status::ready)
		{
			allFinish.store(false);
		}
	}
	if (allFinish.load())	//所有线程在duration内均执行完毕
	{
		for (int thid = 0; thid < 10; thid++)
		{
			std::cout << "[id]=" << thid << ",[tid]= " << std::this_thread::get_id() << "is goint to finish.." << ",ret=" << tasks.at(thid).get() << std::endl;
		}
	}
	else //存在线程在duration内均执行完毕
	{
		std::cout << "not all threads finish in " << durationSec << "s," << "all threads are going to cancel.." << std::endl;
		sts.request_stop();
	}


	////方法2:用户手动输入取消所有线程
	//int flag = -1;
	//std::cin >> flag;
	//if (flag == 0)
	//{
	//	std::cout << "all threads are going to cancel.." << std::endl;
	//	sts.request_stop();
	//}

	return 0;
}


posted @ 2025-07-15 21:50  仰望星河Leon  阅读(19)  评论(0)    收藏  举报