我有一个将图像作为原始数据转储到磁盘的线程。它可以正常工作几分钟然后突然停止做任何事情。
通过命令行输出我发现它在循环内的随机位置停止。
程序在这个线程中没有崩溃(它在线程停止运行后不久崩溃,因为我的图像缓冲区已满),所以线程中没有错误/异常/任何内容。
这是我的代码草图:
class ImageWriter
{
public:
// constructor, destructor
void continueWriting();
private:
void writeImages();
std::thread m_WriterThread;
bool m_WriterThreadRunning;
std::mutex m_ThreadRunningMutex;
ImageManager * m_ImageManager;
};
ImageWriter::continueWriting()
{
// whenever a new image is acquired, this function is called
// so if the thread has finished, it needs to be restarted
// this function is also used for the first start of writing
m_ThreadRunningMutex.lock();
if ( m_WriterThreadRunning )
{
m_ThreadRunningMutex.unlock();
}
else
{
m_ThreadRunningMutex.unlock();
if( m_WriterThread.joinable() )
{
m_WriterThread.join();
}
m_WriterThreadRunning = true;
m_WriterThread = std::thread( &ImageWriter::writeImages, this );
}
}
void ImageWriter::writeImages()
{
while ( true )
{
// MyImage is a struct that contains the image pointer and some metadata
std::shared_ptr< MyImage > imgPtr = m_ImageManager->getNextImage(m_uiCamId);
if( imgPtr == nullptr )
{
// this tells the ImageWriter that currently there are no further images queued
break;
}
// check whether the image is valid. If it's not, skip this image and continue with the next one
[...]
// create filename
std::stringstream cFileNameStr;
cFileNameStr << [...];
std::ofstream cRawFile( cFileNameStr.str().c_str(), std::ios::out | std::ios::binary );
unsigned char * ucDataPtr = imgPtr->cImgPtr;
if( cRawFile.is_open() )
{
// calculate file size
unsigned int uiFileSize = [...];
cRawFile.write(reinterpret_cast<char*>(ucDataPtr), uiFileSize);
cRawFile.close();
}
// dump some metadata into a singleton class for logging
[...]
}
m_ThreadRunningMutex.lock();
m_WriterThreadRunning = false;
m_ThreadRunningMutex.unlock();
}
ImageManager是一个负责图像采集并对采集的图像进行排队的类。它还会触发continueWriting()。 continueWriting()机制是必要的,因为图像的写入速度可能比获取的速度快。
为什么这个线程在随机位置随机停止运行且没有任何错误?
瓦尔格林德并没有在我的控制范围内产生任何东西。 我尝试设置线程的优先级,但这并没有任何区别。 我也尝试了另一个磁盘,但这也没有任何区别。答案 0 :(得分:0)
我注意到你立刻解锁了两个分支中的线程。既然你所做的只是阅读布尔,你可能应该完全避免使用锁。读取通常不是需要同步的操作(除非它有副作用,例如读取流,或者取消分配位置等)
考虑一下:在真实之前你永远不会从那个bool中读取一个True值,并且因为你所做的只是读取,你将永远不会冒这个函数给那个bool赋值不正确的风险。在您加入线程之前,您不会在此处为bool分配新值。
我假设这里发生的事情是你的代码锁定了互斥锁,而另一个线程试图写入它,但是因为它被锁定了所以不能。