我想创建一个将在其自己的线程上运行的事件循环类,支持将任务添加为std::functions
并执行它们。
为此,我从这里使用SafeQueue:https://stackoverflow.com/a/16075550/1069662
class EventLoop
{
public:
typedef std::function<void()> Task;
EventLoop(){ stop=false; }
void add_task(Task t) { queue.enqueue(t); }
void start();
void stop() { stop = true; }
private:
SafeQueue<Task> queue;
bool stop;
};
void EventLoop::start()
{
while (!stop) {
Task t = queue.dequeue(); // Blocking call
if (!stop) {
t();
}
}
cout << "Exit Loop";
}
然后,你会像这样使用它:
EventLoop loop;
std::thread t(&EventLoop::start, &loop);
loop.add_task(myTask);
// do smth else
loop.stop();
t.join();
我的问题是:如何优雅地停止线程? 由于阻塞队列调用,此处不能退出循环。
答案 0 :(得分:5)
排出毒药#39;停止任务。取消阻塞队列等待,并直接请求线程清理并退出或允许消费者线程检查“停止”。布尔值。
假设您需要在应用程序终止之前停止线程/任务。如果我能逃脱它,我通常会尽量不这样做。
答案 1 :(得分:1)
另一种方法:只排队引发异常的任务。对您的代码进行一些更改:
class EventLoop {
// ...
class stopexception {};
// ...
void stop()
{
add_task(
// Boring function that throws a stopexception
);
}
};
void EventLoop::start()
{
try {
while (1)
{
Task t = queue.dequeue(); // Blocking call
t();
}
} catch (const stopexception &e)
{
cout << "Exit Loop";
}
}
对于那些对它们过敏的人,不使用异常的替代方法是将Task重新定义为将EventLoop引用作为其唯一参数的函数,并且stop()将设置的任务排队突破主循环的旗帜。