VS2019创建线程触发C2672 'invoke'错误,求解决方案
解决VS2019中std::thread创建时的C2672 "invoke"编译错误
我在VS2019中尝试创建4个线程并打印调试信息做测试,但编译时触发C2672 "invoke"错误。多次修改函数调用方式仍无法解决,希望得到解决建议。
相关代码
成员变量定义:
std::mutex task_lock; std::mutex running_tasks_lock; std::vector<std::string> path; std::vector<std::thread *> vecOfThreads;
函数实现:
void __get_fileTree(std::thread *thread) { qDebug() << "YES"; } void MapSorter::get_fileTree() { task_lock.lock(); path.push_back("D:\\ymir work\\"); task_lock.unlock(); vecOfThreads.clear(); for (int i = 0; i < 4; i++) { vecOfThreads.push_back(new std::thread(__get_fileTree, this)); } bool tasks_done_ticker = 4; while (tasks_done_ticker > 0) { Sleep(10); running_tasks_lock.lock(); task_lock.lock(); if (path.empty()) { tasks_done_ticker -= 1; } else { tasks_done_ticker = 4; } running_tasks_lock.unlock(); task_lock.unlock(); } for (std::thread *s : vecOfThreads) { s->join(); } }
曾尝试修改为以下代码,仍无法解决问题:
vecOfThreads.push_back(new std::thread(&MapSorter::Repeatget_fileTree, this));
问题根源
- 全局函数
__get_fileTree的参数是std::thread*,但创建线程时传递的是this(MapSorter*类型),参数类型完全不匹配,导致std::thread无法正确调用该函数,触发invoke错误。 - 若改用类成员函数,非静态成员函数必须绑定对象实例才能被
std::thread调用,且函数签名必须和传递的参数匹配,否则同样会报错。
解决步骤
方案一:调整全局函数的参数和调用
如果要继续用全局函数,直接去掉无用的std::thread*参数(测试代码里根本没用到它):
void __get_fileTree() { qDebug() << "YES"; }
创建线程时直接调用:
vecOfThreads.push_back(new std::thread(__get_fileTree));
方案二:使用类成员函数作为线程入口
如果要使用MapSorter的成员函数,有两种方式:
- 静态成员函数:静态成员函数不需要对象实例即可调用
class MapSorter { public: static void Repeatget_fileTree() { qDebug() << "YES"; } // 其他成员定义 };
创建线程:
vecOfThreads.push_back(new std::thread(&MapSorter::Repeatget_fileTree));
- Lambda捕获
this:适合需要访问类成员变量的场景,灵活度更高
for (int i = 0; i < 4; i++) { vecOfThreads.push_back(new std::thread([this]() { qDebug() << "YES"; // 这里可以直接访问MapSorter的成员,比如path、task_lock等 })); }
额外优化建议
- 避免手动调用
lock()/unlock(),用std::lock_guard实现RAII自动解锁,防止死锁:
// 替换手动加锁解锁 { std::lock_guard<std::mutex> lock(task_lock); path.push_back("D:\\ymir work\\"); } // 离开作用域自动解锁
- 当前
tasks_done_ticker的逻辑有问题:线程没有消费path中的内容,只要path不为空就重置计数器,循环会无限运行。需要补充线程处理path元素的逻辑,才能让循环正常结束。 - 尽量用
std::vector<std::thread>代替std::vector<std::thread*>,不需要手动管理内存,更安全:
std::vector<std::thread> vecOfThreads; // 创建线程 vecOfThreads.emplace_back(__get_fileTree); // 等待线程结束 for (auto& t : vecOfThreads) { t.join(); }
内容的提问来源于stack exchange,提问作者x3Syntax
相关产品推荐
相关产品推荐

