将CSocket传递到std::thread

Passing CSocket to std::thread

本文关键字:std thread CSocket      更新时间:2023-10-16

我正在使用CSocket编写多线程服务器。所以,和往常一样,我有监听服务器套接字,并且需要为每个连接的客户端创建接收套接字。为了提供多个客户端处理,我想为每个客户端创建新的std::threaddetach-it,然后在线程函数内处理这个客户端。


我正试着这样做:

int client_handler(CSocket receiver)
{
return 1;
}
CSocket server;
BOOL created = server.Create(12345);
server.Listen();
while(true)
{
CSocket receiver;
if (server.Accept(receiver))
{
std::thread handler(client_handler, receiver);
}
}
...

我在std::thread实例化时遇到编译器错误:

error C2664: 'std::tuple<int (__cdecl *)(CSocket),CSocket>::tuple(std::tuple<int (__cdecl *)(CSocket),CSocket> &&)': cannot convert argument 1 from 'int (__cdecl &)(CSocket)' to 'std::allocator_arg_t'

我读过std::thread文档,但仍然不明白——为什么不能将СSocket传递给?

问题:

在线程实例化中使用CSocket对象,并通过值传递它。传递给std::thread的可调用参数应是可移动的或可复制的。不幸的是,CSocket既不可复制也不可移动,这就是为什么会出现错误的原因。

解决方案:

另一种选择是通过引用传递套接字。在这种情况下,为了避免线程接收到对副本的引用,您必须使用std::ref()包装它。但是您不能在这里考虑这个替代方案,因为receiver是一个具有本地存储的对象。它可能在线程完成之前被销毁,从而导致未定义的行为。

两种可能性:

  1. receiver作为类的成员,或者至少确保它在线程完成之前可用。然后,参考方法将变得可行
  2. 动态创建CSocket,使用shared_ptr并在线程实例化中(以及在client_handler()中)传递该shared_ptr

评论:

虽然与当前问题没有严格关联,但请注意,在您的代码片段中,您创建了handler作为if块的本地对象。因此,当你离开集团而没有加入线程时,对象将被摧毁。这将导致UB:在销毁相应的线程对象之前,必须连接或分离线程。

因此,您可以更改代码的结构以考虑此约束并自行管理线程,也可以考虑使用std::async()以防您只想异步执行接收代码。