gpt4 book ai didi

c++ - 如何可靠地结束被 IO 任务阻塞的线程

转载 作者:行者123 更新时间:2023-12-04 12:28:58 32 4
gpt4 key购买 nike

我有一个执行线程的类,以便不断从给定的 istream 中读取行,然后在内部进行解析。在某些时候,我希望它结束​​,但由于 getline()调用阻塞,它可能永远等待 join() .

#pragma once

#include <thread>
#include <iostream>

class Parser {
private:
std::istream& input;
std::thread parserThread;

public:
Parser(std::istream& input_) : input(input_)/* ... */{}

~Parser() {
stop();
}

void start() {
// Avoid multiple threads...
parserThread = std::thread(&Parser::monitorThread, this);
}


void stop() {
continueParsing = false;
parserThread.join(); // Wait for it to finish
continueParsing = true; // Allow to start another thread at a later point
}


private:
void monitorThread() {
std::string buffer;

// Constantly reads new input until it's told to stop
while(std::getline(input, buffer) && continueParsing) {
//...
}

}
};
有没有标准的方法来实现这一点?或者我的方法(永远读一个线程)是错误的?如果是 C 我只会杀死线程...

最佳答案

std::getline遇到文件尾,则立即返回并停止阻塞。因此,如果您能以某种方式安排在您希望线程退出时发生这种情况,那么这可能是最好的解决方案。但是,如果这是不可能的,那么恐怕 ISO C++ 本身并没有提供任何解决问题的方法。
但是大多数平台都提供特定于平台的扩展,允许您一次等待多个内核对象。例如,Linux 提供 poll epoll 它允许您等待文件描述符上的输入并等待同一函数调用中的事件对象(实际上,Linux 也将事件对象视为文件描述符)。 Microsoft Windows 提供与 WaitForMultipleObjects 类似的功能.
您可以创建一个事件对象(在 Linux 上使用 eventfd ,在 Windows 上使用 CreateEvent )并在您希望线程取消等待并退出时将此事件对象设置为有信号。如果线程正在等待事件对象变为信号或文件描述符上的新输入,那么一旦事件变为信号,它就会停止等待。这样,在等待文件描述符上的新输入时,您将不再遇到线程阻塞的问题。
如果您想实现此解决方案并继续使用 std::istream对于输入,那么您可能需要考虑派生自己的 std::streambuf 实现成员函数的类 underflow 以这样一种方式,它首先调用特定于平台的函数之一 poll/epoll/WaitForMultipleObjects等待新输入可用或退出事件发出信号。如果发出退出事件信号,则函数 underflow应该返回 Traits::eof() ,这将导致 eofbit std::istream待设置和std::getline立即返回。否则,一旦报告有新输入可用,您就可以调用特定于平台的函数之一 read / ReadFile 填充 std::streambuf 的获取区域对象,根据需要调整对象的指针。

关于c++ - 如何可靠地结束被 IO 任务阻塞的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68145364/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com