将CSocket传递给std :: thread

时间:2016-06-03 11:12:29

标签: c++ multithreading sockets c++11

我正在使用CSocket编写多线程服务器。因此,通常情况下,我有监听服务器套接字,并需要为每个连接的客户端创建接收套接字。为了提供多个客户端处理,我想为每个客户端std::thread创建新的detach,然后在线程函数内部处理此客户端。

我想这样做:

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无法传递给?

1 个答案:

答案 0 :(得分:0)

<强>问题:

您在线程实例化中使用CSocket对象,并按值传递它。传递给std::thread的callable的参数应该是可移动的或可复制的。不幸的是,CSocket既不可复制也不可移动,这就是您收到错误的原因。

<强>解决方案:

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

然后有两种可能性:

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

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

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