使用std::future
和ThreadPool
时我遇到了一个相当奇怪的情况,虽然我不认为它是ThreadPool
(我正在使用https://github.com/bandi13/ThreadPool/blob/master/example.cpp)因为(我'我试过它的多个分叉,经过一些调试后,我看不出它与问题有什么关系)。
问题在于,在某些情况下,我的doProcess
方法只是天堂 - 它不会返回。它只是在长时间运行的循环中消失。
因此,我认为我必须做错事,但无法弄清楚是什么。
以下是代码:
ThreadPool pool(numThreads);
std::vector< std::future<bool> > futures;
int count = 0;
string orgOut = outFile;
for (auto fileToProcess : filesToProcess) {
count++;
outFile = orgOut + std::to_string(count);
// enque processing in the thread pool
futures.emplace_back(
pool.enqueue([count, fileToProcess, outFile, filteredKeys, sql] {
return doProcess(fileToProcess, outFile, filteredKeys, sql);
})
);
}
然后我等待所有处理完成(我认为这也可以以更优雅的方式完成):
bool done = false;
while (!done) {
done = true;
for (auto && futr : futures) {
auto status = futr.wait_for(std::chrono::milliseconds(1));
if (status != std::future_status::ready) {
done = false;
break;
}
}
}
编辑:起初我也尝试了obvius wait(),但结果相同:
bool done = false;
while (!done) {
done = true;
for (auto && futr : futures) {
futr.wait();
}
}
编辑:doProcess()方法。行为是这样的:loopcnt变量只是一个计数器,用于调试方法输入和循环开始的频率。正如你所看到的,这个循环没有返回,但线程在这个循环内部消失时没有任何错误,并且偶尔只得到HereCnt(就像运行方法的100次中一样)。我真的很困惑。
bool doProcess([...]) {
// ....
vector<vector<KVO*>*>& features = filter.result();
vector<vector<KVO*>*> filteredFeatures;
static int loopcnt = 0;
std::cout << "loops " << loopcnt << endl;
loopcnt++;
for (vector<KVO*>* feature : features) {
for (KVO *kv : *feature) {
switch (kv->value.type()) {
case Variant::JNULL:
sqlFilter.setNullValue(kv->key);
break;
case Variant::INT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
case Variant::UINT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
case Variant::DOUBLE:
sqlFilter.setValue(static_cast<double>(kv->value), kv->key);
break;
case Variant::STRING:
sqlFilter.setValue(static_cast<string>(kv->value), kv->key);
break;
default:
assert(false);
break;
}
}
int filterResult = sqlFilter.exec();
if (filterResult > 0) {
filteredFeatures.push_back(feature);
}
sqlFilter.reset();
}
static int wasHereCnt = 0;
std::cout << "was here: " << wasHereCnt << endl;
wasHereCnt++;
JsonWriter<Writer<FileWriteStream>> geojsonWriter(writer, filteredFeatures);
bool res = geojsonWriter.write();
os.Flush();
fclose(fp);
return res;
}
doProcess
方法在花费较少时间时可以正常工作。当需要更多时间时,它会中断并消失。差异只是我在方法中运行的SQL查询的复杂性。所以我不发布doProcess()
的代码。
是什么原因导致线程池的线程被中断,以及如何解决它?
更新
好吧,我发现了。几个小时后,我决定删除未来的任务,然后在主线程上运行任务。问题是通过以下方式抛出异常:
抛出std :: runtime_error(“bad cast”);
...在此之后的代码流程中有一段时间了:
case Variant::UINT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
在主线程上运行时,此错误按预期抛出。但是,当它作为未来任务运行时,它永远不会被提升。这真的很奇怪,看起来像编译器或调试器问题。