将CSocket传递到std::thread
Passing CSocket to std::thread
我正在使用CSocket
编写多线程服务器。所以,和往常一样,我有监听服务器套接字,并且需要为每个连接的客户端创建接收套接字。为了提供多个客户端处理,我想为每个客户端创建新的std::thread
,detach
-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
是一个具有本地存储的对象。它可能在线程完成之前被销毁,从而导致未定义的行为。
两种可能性:
- 将
receiver
作为类的成员,或者至少确保它在线程完成之前可用。然后,参考方法将变得可行 - 动态创建CSocket,使用
shared_ptr
并在线程实例化中(以及在client_handler()
中)传递该shared_ptr
评论:
虽然与当前问题没有严格关联,但请注意,在您的代码片段中,您创建了handler
作为if
块的本地对象。因此,当你离开集团而没有加入线程时,对象将被摧毁。这将导致UB:在销毁相应的线程对象之前,必须连接或分离线程。
因此,您可以更改代码的结构以考虑此约束并自行管理线程,也可以考虑使用std::async()
以防您只想异步执行接收代码。
相关文章:
- 在std::thread中,joinable()然后join()线程安全吗
- 分离一个静态常量 std::thread?
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 如何从 std::thread 返回值
- 将 std::thread by 值推送到列表中
- 转发变量参数列表以模拟 std::thread
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- std::thread 增加 DLL 引用计数,从而防止卸载 DLL
- 如何防止 std::thread 在 QT 中冻结 GUI?
- 对带有唯一指针的 std::thread 使用类成员函数时出现编译错误
- 为什么参数在构造 std::thread 时移动两次
- std::thread::_Invoker 使用线程编程时出错
- 在线程 A 中创建一个 std::thread 对象,在线程 B 中连接
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- ZeroMQ 在使用 std::thread 创建工作线程时崩溃
- 在没有复制构造函数的对象的成员函数中启动 std::thread
- CLang:在 std::thread 中运行函数会导致结构创建BAD_ACCESS
- 调用以CWinThread为基的类运算符()的std::thread失败
- 如何通过std::thread生成多个线程
- std::future::get()或std::future::wait()是std::thread::join()的替