在把点云数据写入本地时用到了多线程方法,对于每一秒内的20个frame,分别启用一个线程进行数据写入,这样做会导致点云数据条目有个别错误,表示一个点的信息的一行数据应当包含且仅包含xyz,反射率和时间戳,但是实际生成的文件里总会有个别几条信息出现数据条目个数不对,或者数值明显错误的现象。之前采取的解决办法是,在写入文件和读文件之前用一个判断来进行过滤,但是治标不治本。今天发现livox sdk里在保存lvx文件时使用的mutex互斥锁可以用在这里,在以点为单位进行循环写文件的过程中,在写入每一个点的信息之前加上一句std::unique_lock<std::mutex> lock(mtx);
避免多个线程同时对文件进行写入操作导致数据条目混乱,点云数据的出错几率极大降低。
std::unique_lock<std::mutex> lock(mtx);
for (int j = 0; j < 4; j++)
{
fprintf(fOutput, "%d", nPointData[i][j]);
fputc(',', fOutput);
}
fprintf(fOutput, "\n");
mtx变量可以声明为全局变量或类的成员变量。
设计的MFC界面有两个主要功能,一个是把每秒的数据分别保存并依次在实时预览窗格显示。另一个是保存所需要的数据到本地并在预览窗格显示。这两个功能都写在了主线程里,所以其中一个在运行的时候整个界面就会卡死。而在进行实时预览的过程中界面卡住是不可接受的,所以要把实时点云获取和显示在另外开辟的线程里执行。
先把实时点云的获取和显示的按键响应函数里的内容移动到一个静态函数里,声明方式:
static UINT FuncName(LPVOID lpParam)
{
……
return 0;
}
随后在按键响应函数里创建一个线程并调用上面这个静态函数:
m_WinThread = AfxBeginThread(FuncName, NULL, THREAD_PRIORITY_NORMAL, 0, 0, NULL);
其中m_WinThread需要在对话框类的头文件里声明,为了后续方便可以初始化为NULL:
CWinThread* m_WinThread = NULL;
这样点击按钮之后,就可以正常进行实时显示了,同时界面不会卡死。在需要暂停的地方把线程挂起,比如另一个按钮的响应函数里或者对话框的销毁函数里,为了避免在线程未创建的情况下将其挂起,加一个if判断:
if(m_WinThread!=NULL)
m_WinThread->SuspendThread();
参考https://blog.csdn.net/hushiwei1993/article/details/44974947