0

我的代码中有一个线程向量,我在其中推送线程。在对函数“func”进行约 100 次调用后,我得到“在没有活动异常的情况下终止调用”。我读过这个错误意味着没有为线程调用“加入”。在下面的代码中,我为向量中的每个线程调用“join”,在我的程序中,我已经调用了大约 100 次函数,但是如果我再次调用它,代码就会崩溃。一个线程,比如说thread_10,是否有可能在第一个'for'循环结束之前完成,并且到第二个'join'函数不能被调用,因为对于thread_10,因为没有这样的线程?
如果有可能,我该如何防止这种情况?

void func(){
    vector<std::thread> my_threads;
    for (deque<unsigned int>::iterator it = candidates.begin(); it != candidates.end(); it++)  
    {       
        Query* quer = &queries[*it];
        my_threads.push_back(std::thread(foo, param));  
    }     

    for (std::thread &thread: my_threads)
    {  
        thread.join();
    }
}
4

1 回答 1

2

如果函数的第一部分抛出异常,例如因为没有足够的资源来创建新线程,那么函数会因异常而中止,而不加入已经创建的线程。很可能这就是您看到terminate 被调用而没有活动异常的原因。

以下应该有效:

std::vector<std::thread> threads;
SCOPE_EXIT {
    for (auto&& thread : threads) {
        thread.join();
    }
};
for (auto&& candidate : candidates) {
    // ...
    threads.emplace_back(callable, candiate, ...);
}

编辑: SCOPE_EXIT是一个众所周知的构造,例如在folly library的标头ScopeGuard中定义。我已经用它来说明,清理必须发生在函数(范围)的末尾——不管它是定期退出还是在异常中退出。

于 2013-06-19T17:27:54.537 回答