You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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));

问题根源

  1. 全局函数__get_fileTree的参数是std::thread*,但创建线程时传递的是this(MapSorter*类型),参数类型完全不匹配,导致std::thread无法正确调用该函数,触发invoke错误。
  2. 若改用类成员函数,非静态成员函数必须绑定对象实例才能被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等
    }));
}

额外优化建议

  1. 避免手动调用lock()/unlock(),用std::lock_guard实现RAII自动解锁,防止死锁:
// 替换手动加锁解锁
{
    std::lock_guard<std::mutex> lock(task_lock);
    path.push_back("D:\\ymir work\\");
} // 离开作用域自动解锁
  1. 当前tasks_done_ticker的逻辑有问题:线程没有消费path中的内容,只要path不为空就重置计数器,循环会无限运行。需要补充线程处理path元素的逻辑,才能让循环正常结束。
  2. 尽量用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:20:30