C++ 从另一个线程取消阻止一个线程

C++ 从另一个线程取消阻止一个线程,c++,multithreading,pthreads,C++,Multithreading,Pthreads,我正在寻找一种方法,能够在从网络接收数据的同时向终端输入数据 为此,我创建了一个新线程dataCapture(std::thread),它将使用std::cin获取输入。主线程是接收器 当网络发送字符串“end”时,程序需要退出 以下是简化代码: void dataCapture() while (! quit) { std::string data; std::cout << "Enter data: "; std::cin

我正在寻找一种方法,能够在从网络接收数据的同时向终端输入数据

为此,我创建了一个新线程
dataCapture
std::thread
),它将使用
std::cin
获取输入。主线程是接收器

当网络发送字符串“end”时,程序需要退出

以下是简化代码:

void dataCapture()
    while (! quit) {
        std::string data;
        std::cout << "Enter data: ";
        std::cin >> data;
    }
}

bool quit=false;

int main() {
    // socket creation
    // connection to server
    const std::string quit_value = "end";


    std::thread datacapture_T(dataCapture);

    while (! quit) {
        char recep[1024];
        recv(sd, recep, sizeof(recep),0);
        if (recep == quit_value) {
            quit=true;
        }
    }
    datacapture_T.join();
    return 0;
}
void dataCapture()
而(!退出){
std::字符串数据;
std::cout>数据;
}
}
bool-quit=false;
int main(){
//套接字创建
//与服务器的连接
const std::string quit_value=“end”;
线程数据捕获(datacapture);
而(!退出){
char-recep[1024];
recv(标准偏差,recep,尺寸(recep),0);
if(recep==退出值){
退出=真;
}
}
datacapture_T.join();
返回0;
}
这不起作用,因为在接收到
“end”
后,
main
阻塞了
datacapture\u t.join()
,因为
datacapture
std::cin
调用中被阻塞

是否可以从main中取消阻止
数据捕获
线程

如果没有,是否有可能强行杀死它

注:为了简化,我没有包括锁


谢谢你的帮助

您可以使用
ctrl-z
关闭
std::cin

另一种解决方法是进入
dataCapture()
并通过执行
break
检查
quit\u值


<>编辑:考虑使用原子,以尽可能好地保持对并发线程的读/写。不要认为它增加了太多的复杂性

无论在理论上还是在实践中,都没有干净的方法可以通过编程杀死线程

以编程方式取消阻止和关闭等待输入(任何类型)的线程的标准方法是使用
select()
pipe()

  • 创建管道()
  • select()
    创建一个文件描述符集,其中包含您的输入文件描述符、
    read()
    pipe()
  • 不要在
    cin
    上执行阻塞读取,而是对
    select()
    执行阻塞调用
  • 如果
    select()
    告诉您要从
    管道()读取某些内容,请退出线程。您可以清理所有资源并完成所有处理,因为您正在线程中检测终止请求。这是关键
  • 如果
    select()
    告诉您需要从cin读取某些内容,请读取并处理它
  • 从任何其他螺纹,例如在main()的末端:
    • 每当您想要终止线程时,将一个字节(值无关紧要)写入
      管道()
    • join()
      线程
你觉得这个方法听起来很武断和复杂吗?它是!然而,这是一种常见的做法,您可以依靠它来工作,因为许多框架和程序都使用它

还有一些不太好的选择,比如轮询输入(非阻塞)和检查停止标志。也许最有用的替代方法是根本不使用任何其他线程来获取输入,对所有I/O使用单线程事件驱动系统,只在其他线程中进行内部处理


线程不是实现I/O并发的有用机制。线程对于创建CPU处理并发性非常有用。

尝试关闭
std::cin
您可以将quit作为引用传递给线程方法(必须在使用std::ref的线程中显式执行),然后在主线程中更改它时,它将使线程方法退出。@PaulSanders对不起,我该怎么做?你的意思是关闭stdin吗?如果是,该程序实际上会在加入后调用另一个使用
std::cin
的函数,那么我能重新打开它吗?@RasmusDall我想我不理解你的想法抱歉。问题在于线程在
std::cin
上被阻塞,而不是它无法检测到
quit
changed value
cin
不是为此而构建的。为了获得最佳效果,您必须使用允许终止或超时的系统特定调用。一个例子:这非常有效,谢谢!我还尝试了一种方法,在(!quit)
循环时,select处于
状态,并且每1秒超时一次,这种方法是:如果stdin上有输入,它将处理它,否则它将在检查
后执行下一次迭代!退出
。这是不是表现不佳?调用无限制超时的select是否在内部具有
while(true)
?@Jonas:
select()
挂起线程并允许其他线程运行,直到有事情要做,因此这是最有效的方法,因为它允许其他线程进程在无事可做的情况下运行。在内部,它不使用轮询,而是直接使用内部操作系统事件。但是很多程序使用1s(大约)的超时作为最后手段,以防pipe()机制失败,实际上对于简单的程序,1s超时更好,因为实现它的代码要少得多,而且通常1s最坏情况下的终止延迟是可以接受的。