当前位置:   article > 正文

C++创建线程实现自动保存队列中的数据_c++保存线程队列然后同时启动

c++保存线程队列然后同时启动

多线程

互斥量mutex

CreateMutex()函数可用来创建一个有名或无名的互斥量对象

互斥量:

 采用互斥对象机制。互斥锁,像一个物件,这个物件只能同时被一个线程持有。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。

互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。

  1. WINBASEAPI
  2. __out_opt
  3. HANDLE
  4. WINAPI
  5. CreateMutexA(
  6. __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
  7. __in BOOL bInitialOwner,
  8. __in_opt LPCSTR lpName
  9. );
  10. WINBASEAPI
  11. __out_opt
  12. HANDLE
  13. WINAPI
  14. CreateMutexW(
  15. __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
  16. __in BOOL bInitialOwner,
  17. __in_opt LPCWSTR lpName
  18. );
  19. #ifdef UNICODE
  20. #define CreateMutex CreateMutexW
  21. #else
  22. #define CreateMutex CreateMutexA
  23. #endif // !UNICODE

参数说明:

lpMutexAttributes:指向安全属性的指针

bInitialOwner:初始化互斥对象的所有者

 lpName:指向互斥对象名的指针

创建一个互斥量:

  1. HANDLE m_hMutex = CreateMutex(NULL /*默认安全属性*/
  2. , false /*创建线程不拥有该信号量*/
  3. , NULL /*锁名称*/
  4. );

事件event

CreateEvent是一个windows api函数。它用来创建或打开一个命名的或无名的事件对象

  1. HANDLECreateEvent(
  2. LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性
  3. BOOL bManualReset,// 复位方式,手动或自动
  4. BOOL bInitialState,// 初始状态
  5. LPCTSTR lpName // 对象名称
  6. );

bManualReset:

TRUE:必须用ResetEvent函数来手工将事件的状态复原到无信号状态;FALSE,当一个等待线程被释放以后,系统将会自动将事件状态复原为无信号状态

bInitialState:true,初始状态为有信号。

事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。

实例:创建线程自动保存队列信号

调用demo

 

源代码

**.h

  1. #pragma once
  2. #include <vector>
  3. #include <queue>
  4. using namespace std;
  5. class CMySaveData
  6. {
  7. public:
  8. CMySaveData(void);
  9. ~CMySaveData(void);
  10. CMySaveData(const CMySaveData& copy);
  11. CMySaveData& operator = (const CMySaveData& assign);
  12. //光程电机位置
  13. int m_opPos;
  14. //屈光电机位置
  15. int m_refPos;
  16. //Z电机位置
  17. int m_motoZPos;
  18. //图片编号
  19. int m_imgNum;
  20. };
  21. enum ENU_DATA_TYPE
  22. {
  23. ISO,
  24. OCT
  25. };
  26. class DataSaveRequest
  27. {
  28. public:
  29. DataSaveRequest(ENU_DATA_TYPE enuDataType, CMySaveData mydata);
  30. DataSaveRequest();
  31. ~DataSaveRequest();
  32. CMySaveData m_data;
  33. ENU_DATA_TYPE m_enuDataType;
  34. };
  35. class SaveDataInfo
  36. {
  37. public:
  38. SaveDataInfo(void);
  39. ~SaveDataInfo(void);
  40. private:
  41. HANDLE m_Mutex;
  42. HANDLE m_ExitEvent;
  43. bool m_bIsThreadOn;
  44. int m_iSaveCount;
  45. std::queue<DataSaveRequest> m_queueDataInfo;
  46. FILE * m_pfile;
  47. private:
  48. static void SavingThread(void* param);
  49. void Save(const DataSaveRequest& dsr);
  50. DataSaveRequest PopDataSaveRequest();
  51. void SaveMyData(DataSaveRequest dsr);
  52. void PushBackDataSaveRequest(const DataSaveRequest& dsr);
  53. public:
  54. void Stop();
  55. void SetMyData(CMySaveData myData);
  56. void Begin(const CString &strFileDirPath,ENU_DATA_TYPE type);
  57. };

**.cpp

  1. #include "StdAfx.h"
  2. #include "SaveDataInfo.h"
  3. #include <WinBase.h>
  4. DataSaveRequest::DataSaveRequest(ENU_DATA_TYPE enuDataType, CMySaveData mydata)
  5. :m_enuDataType(enuDataType),m_data(mydata)
  6. {
  7. }
  8. DataSaveRequest::DataSaveRequest()
  9. {
  10. m_enuDataType=ISO;
  11. }
  12. DataSaveRequest::~DataSaveRequest()
  13. {
  14. }
  15. CMySaveData::CMySaveData(void)
  16. {
  17. }
  18. CMySaveData::~CMySaveData(void)
  19. {
  20. }
  21. CMySaveData::CMySaveData(const CMySaveData& copy)
  22. {
  23. //CLog::GetInstance()->WriteLog(_T("MyLine::MyLine(const MyLine& copy)"));
  24. m_refPos=copy.m_refPos;
  25. m_motoZPos=copy.m_motoZPos;
  26. m_opPos=copy.m_opPos;
  27. m_imgNum=copy.m_imgNum;
  28. }
  29. CMySaveData& CMySaveData::operator = (const CMySaveData& assign)
  30. {
  31. if(this != &assign){
  32. m_refPos=assign.m_refPos;
  33. m_opPos=assign.m_opPos;
  34. m_motoZPos=assign.m_motoZPos;
  35. m_imgNum=assign.m_imgNum;
  36. }
  37. return *this;
  38. }
  39. SaveDataInfo::SaveDataInfo(void)
  40. {
  41. m_bIsThreadOn = false;
  42. m_Mutex = CreateMutex(NULL, FALSE, NULL);
  43. //ResetEvent手动将事件的状态复原到无信号状态,初始状态没没有信号
  44. m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, _T("m_ExitEvent"));
  45. }
  46. SaveDataInfo::~SaveDataInfo(void)
  47. {
  48. fclose (m_pfile);
  49. CloseHandle(m_Mutex);
  50. CloseHandle(m_ExitEvent);
  51. }
  52. void SaveDataInfo::Begin(const CString &strFileDirPath,ENU_DATA_TYPE type)
  53. {
  54. if (m_bIsThreadOn)
  55. {
  56. //如果线程已经创建,直接返回
  57. return;
  58. }
  59. BOOL bIsDirNormal = TRUE;
  60. if (!PathIsDirectory(strFileDirPath))
  61. {
  62. //如果路径不存在创建路径
  63. bIsDirNormal = CreateDirectory(strFileDirPath, NULL);
  64. }
  65. if(!bIsDirNormal)
  66. {
  67. //创建路径失败,直接返回
  68. return;
  69. }
  70. m_iSaveCount = 0;
  71. m_bIsThreadOn = true;
  72. CString filePath;
  73. if (ISO == type)
  74. {
  75. filePath.AppendFormat(_T("%s/ISO_PosInfo.txt"), strFileDirPath);
  76. }
  77. else if (OCT == type)
  78. {
  79. filePath.AppendFormat(_T("%s/ISO_PosInfo.txt"), strFileDirPath);
  80. }
  81. const size_t strSize=(filePath.GetLength()+1)*2;
  82. char* pstr=new char[strSize];
  83. size_t sz=0;
  84. wcstombs_s(&sz,pstr,strSize,filePath,_TRUNCATE);
  85. m_pfile = fopen((const char*)pstr,"w+");
  86. //启动保存数据线程
  87. _beginthread(SavingThread, 0, this);
  88. }
  89. void SaveDataInfo::SavingThread(void* param)
  90. {
  91. SaveDataInfo* pDataSaver = (SaveDataInfo*)param;
  92. //如果保存线程没有退出,或者保存的数据不为空
  93. while (pDataSaver->m_bIsThreadOn || (!pDataSaver->m_queueDataInfo.empty()))
  94. {
  95. if (pDataSaver->m_queueDataInfo.size() <= 0)
  96. {
  97. Sleep(50);
  98. continue;
  99. }
  100. DataSaveRequest dsr = pDataSaver->PopDataSaveRequest();
  101. pDataSaver->Save(dsr);
  102. }
  103. //设置m_ExitEvent为有信号状态,激活m_ExitEvent
  104. SetEvent(pDataSaver->m_ExitEvent);
  105. }
  106. void SaveDataInfo::Stop()
  107. {
  108. //设置m_ExitEvent为无信号状态
  109. ResetEvent(m_ExitEvent);
  110. m_bIsThreadOn = false;
  111. //等待m_ExitEvent事件被激活,m_ExitEvent有信号
  112. WaitForSingleObject(m_ExitEvent, INFINITE);
  113. }
  114. //取出一个保存请求
  115. DataSaveRequest SaveDataInfo::PopDataSaveRequest()
  116. {
  117. DataSaveRequest dsr;
  118. WaitForSingleObject(m_Mutex, INFINITE);
  119. dsr = m_queueDataInfo.front();
  120. m_queueDataInfo.pop();
  121. ReleaseMutex(m_Mutex);
  122. return dsr;
  123. }
  124. void SaveDataInfo::Save(const DataSaveRequest& dsr)
  125. {
  126. SaveMyData(dsr);
  127. }
  128. void SaveDataInfo::PushBackDataSaveRequest(const DataSaveRequest& dsr)
  129. {
  130. WaitForSingleObject(m_Mutex, INFINITE);
  131. m_queueDataInfo.push(dsr);
  132. ReleaseMutex(m_Mutex);
  133. }
  134. void SaveDataInfo::SetMyData(CMySaveData myData)
  135. {
  136. DataSaveRequest dsr(ENU_DATA_TYPE::ISO, myData);
  137. PushBackDataSaveRequest(dsr);
  138. }
  139. void SaveDataInfo::SaveMyData(DataSaveRequest dsr)
  140. {
  141. CMySaveData tmdata=dsr.m_data;
  142. fprintf(m_pfile,"图片编号:%d,\tZ电机位置:%d,\t屈光位置:%d,\t光程位置:%d\n",tmdata.m_imgNum,tmdata.m_motoZPos,tmdata.m_refPos,tmdata.m_opPos);
  143. }

automotodatasaver.h

  1. /************************************************************************/
  2. /* 眼动追踪数据保存(保存追踪过程中的相关数据) */
  3. /************************************************************************/
  4. #pragma once
  5. #include <queue>
  6. //#include "ImgPro.h"
  7. //#include "utility.h"
  8. #include "..\..\..\ImgPro.h"
  9. #include "..\..\utility.h"
  10. class CLog;
  11. namespace MoptimOct{
  12. class AutoMotoDataSaver
  13. {
  14. private:
  15. enum ENU_DATA_TYPE
  16. {
  17. RegisResult,
  18. BaseLso,
  19. RegisLso,
  20. OriginalOct,
  21. Reversed
  22. };
  23. class DataSaveRequest
  24. {
  25. public:
  26. DataSaveRequest(ENU_DATA_TYPE enuDataType, const PUSHORT pData, int iImageWidth = 0, int iImageHeight = 0);
  27. DataSaveRequest();
  28. ~DataSaveRequest();
  29. void Release();
  30. BYTE* m_pData;
  31. int m_iImageWidth;
  32. int m_iImageHeight;
  33. size_t m_iDataSize;
  34. int m_iId;
  35. int m_iNum;
  36. ENU_DATA_TYPE m_enuDataType;
  37. };
  38. CString m_strFileDirPath;
  39. std::queue<DataSaveRequest> m_queueDataInfo;
  40. HANDLE m_Mutex;
  41. bool m_bIsThreadOn;
  42. int m_iSaveCount;
  43. HANDLE m_ExitEvent;
  44. CLog *m_pLog;
  45. public:
  46. AutoMotoDataSaver();
  47. virtual ~AutoMotoDataSaver();
  48. void Begin(const CString &strFilePath);
  49. void Stop();
  50. void SetLsoRegisResultData(const ST_LSO_REGIS_RESULT& stRegisResultData, int iId = 0);
  51. void SetBaseLsoData(const PUSHORT pHDLSO, int width=VEDIOWIDTH, int height=VEDIOHEIGHT, int iId = 0,int iNum=0);
  52. void SetRegisLsoData(const PUSHORT pSmallLSO, int width=SMALL_LSO_WIDTH, int height=SMALL_LSO_HEIGHT, int iId = 0);
  53. void SetOriginalOctData(const PUSHORT pOctOriData, int width, int height, int iId = 0);
  54. private:
  55. void PushBackDataSaveRequest(const DataSaveRequest& dsr);
  56. DataSaveRequest PopDataSaveRequest();
  57. void Save(const DataSaveRequest& dsr);
  58. void SaveBitmapToFile(DataSaveRequest dsr,CString m_szFileName/*PUSHORT pBytes,int num*/);
  59. static void SavingThread(void* param);
  60. };
  61. }

automotodatasaver.cpp

  1. #include "stdafx.h"
  2. #include "AutoMotoDataSaver.h"
  3. #include <process.h>
  4. #include <iostream>
  5. #include <fstream>
  6. #include "../../Log.h"
  7. #include "ProcessFile.h"
  8. namespace MoptimOct{
  9. AutoMotoDataSaver::DataSaveRequest::DataSaveRequest(ENU_DATA_TYPE enuDataType,
  10. const PUSHORT pData, int iImageWidth /*= 0*/, int iImageHeight /*= 0*/)
  11. :m_enuDataType(enuDataType), m_pData(NULL), m_iImageWidth(iImageWidth), m_iImageHeight(iImageHeight),
  12. m_iId(0),m_iNum(0)
  13. {
  14. BYTE *pdata = new BYTE[VEDIOWIDTH * VEDIOHEIGHT *3];
  15. int k = 0;
  16. for(int i = 0;i<VEDIOWIDTH * VEDIOHEIGHT;i++)
  17. {
  18. pdata[k] =(BYTE)pData[i];
  19. pdata[k+1] =(BYTE) pData[i];
  20. pdata[k+2] = (BYTE)pData[i];
  21. k+=3;
  22. }
  23. m_pData = pdata;
  24. }
  25. AutoMotoDataSaver::DataSaveRequest::DataSaveRequest()
  26. :m_enuDataType(RegisResult), m_pData(NULL), m_iImageWidth(0), m_iImageHeight(0),
  27. m_iId(0)
  28. {
  29. }
  30. AutoMotoDataSaver::DataSaveRequest::~DataSaveRequest()
  31. {
  32. }
  33. void AutoMotoDataSaver::DataSaveRequest::Release()
  34. {
  35. if(NULL == m_pData)
  36. {
  37. return;
  38. }
  39. BYTE *pBytes = (BYTE*)m_pData;
  40. delete[] pBytes;
  41. m_pData = NULL;
  42. }
  43. AutoMotoDataSaver::AutoMotoDataSaver():m_bIsThreadOn(false),m_iSaveCount(0),m_pLog(0)
  44. {
  45. m_pLog = CLog::GetInstance();
  46. m_Mutex = CreateMutex(NULL, FALSE, NULL);
  47. m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, _T("m_ExitEvent"));
  48. }
  49. AutoMotoDataSaver::~AutoMotoDataSaver()
  50. {
  51. CloseHandle(m_Mutex);
  52. CloseHandle(m_ExitEvent);
  53. }
  54. void AutoMotoDataSaver::Begin(const CString &strFileDirPath)
  55. {
  56. if (m_bIsThreadOn)
  57. {
  58. CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,if (m_bIsThreadOn)"));
  59. return;
  60. }
  61. BOOL bIsDirNormal = TRUE;
  62. if (!PathIsDirectory(strFileDirPath))
  63. {
  64. CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,if (!PathIsDirectory(strFileDirPath))"));
  65. bIsDirNormal = CreateDirectory(strFileDirPath, NULL);
  66. }
  67. if(!bIsDirNormal)
  68. {
  69. return;
  70. }
  71. m_iSaveCount = 0;
  72. m_strFileDirPath = strFileDirPath;
  73. m_bIsThreadOn = true;
  74. CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,_beginthread(SavingThread, 0, this);"));
  75. _beginthread(SavingThread, 0, this);
  76. }
  77. void AutoMotoDataSaver::Stop()
  78. {
  79. ResetEvent(m_ExitEvent);
  80. m_bIsThreadOn = false;
  81. WaitForSingleObject(m_ExitEvent, INFINITE);
  82. }
  83. void AutoMotoDataSaver::SetLsoRegisResultData(const ST_LSO_REGIS_RESULT& stRegisResultData, int iId)
  84. {
  85. /*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_REGISRESULT))
  86. {
  87. return;
  88. }
  89. DataSaveRequest dsr(AutoMotoDataSaver::RegisResult, (void*)&stRegisResultData);
  90. dsr.m_iId = iId;
  91. PushBackDataSaveRequest(dsr);*/
  92. }
  93. void AutoMotoDataSaver::SetBaseLsoData(const PUSHORT pHDLSO, int width, int height, int iId,int iNum)
  94. {
  95. /*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_HDLSO))
  96. {
  97. return;
  98. }*/
  99. DataSaveRequest dsr(AutoMotoDataSaver::BaseLso, pHDLSO, width, height);
  100. dsr.m_iId = iId;
  101. dsr.m_iNum=iNum;
  102. PushBackDataSaveRequest(dsr);
  103. }
  104. void AutoMotoDataSaver::SetRegisLsoData(const PUSHORT pSmallLSO, int width/*=SMALL_LSO_WIDTH*/, int height/*=SMALL_LSO_HEIGHT*/, int iId)
  105. {
  106. /*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_SMALLHDLSO))
  107. {
  108. return;
  109. }*/
  110. /*DataSaveRequest dsr(AutoMotoDataSaver::RegisLso, (void*)pSmallLSO, width, height);
  111. dsr.m_iId = iId;
  112. PushBackDataSaveRequest(dsr);*/
  113. }
  114. void AutoMotoDataSaver::SetOriginalOctData(const PUSHORT pOctOriData, int width, int height, int iId)
  115. {
  116. /*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_ORIGINALOCT))
  117. {
  118. return;
  119. }*/
  120. /*DataSaveRequest dsr(AutoMotoDataSaver::OriginalOct, (void*)pOctOriData, width, height);
  121. dsr.m_iId = iId;
  122. PushBackDataSaveRequest(dsr);*/
  123. }
  124. void AutoMotoDataSaver::PushBackDataSaveRequest(const DataSaveRequest& dsr)
  125. {
  126. WaitForSingleObject(m_Mutex, INFINITE);
  127. m_queueDataInfo.push(dsr);
  128. ReleaseMutex(m_Mutex);
  129. }
  130. AutoMotoDataSaver::DataSaveRequest AutoMotoDataSaver::PopDataSaveRequest()
  131. {
  132. DataSaveRequest dsr;
  133. WaitForSingleObject(m_Mutex, INFINITE);
  134. dsr = m_queueDataInfo.front();
  135. m_queueDataInfo.pop();
  136. ReleaseMutex(m_Mutex);
  137. return dsr;
  138. }
  139. void AutoMotoDataSaver::Save(const DataSaveRequest& dsr)
  140. {
  141. CString filePath;
  142. if (RegisResult == dsr.m_enuDataType)
  143. {
  144. filePath.AppendFormat(_T("%s/RegisResult.txt"), m_strFileDirPath);
  145. ST_LSO_REGIS_RESULT* pRegisResult = (ST_LSO_REGIS_RESULT*)dsr.m_pData;
  146. CString strRegisResult;
  147. strRegisResult.AppendFormat(_T("ID=%d state=%d xOffset=%lf yOffset=%lf\r\n"),
  148. dsr.m_iId, (int)(pRegisResult->state), pRegisResult->xOffset, pRegisResult->yOffset);
  149. #ifdef UNICODE
  150. std::wofstream ofs(filePath, std::ios::out | std::ios::app);
  151. ofs << strRegisResult.GetBuffer();
  152. #else
  153. std::ofstream ofs(filePath, std::ios::out);
  154. ofs << strRegisResult;
  155. #endif
  156. }
  157. else
  158. {
  159. if (BaseLso == dsr.m_enuDataType)
  160. {
  161. filePath.AppendFormat(_T("%s%d.BMP"), m_strFileDirPath, dsr.m_iNum/*,dsr.m_iId*/);
  162. CLog::GetInstance()->WriteLog(_T("保存虹膜图,SaveBitmapToFile,dsr.m_iNum: %d,dsr.m_iId: %d"),dsr.m_iNum,dsr.m_iId);
  163. //CLog::GetInstance()->WriteLog(filePath);
  164. SaveBitmapToFile(dsr,filePath);
  165. }
  166. else if(RegisLso == dsr.m_enuDataType)
  167. {
  168. filePath.AppendFormat(_T("%s/RegisLso_%d.bin"), m_strFileDirPath, /*dsr.m_iNum,*/dsr.m_iId);
  169. }
  170. else if(OriginalOct == dsr.m_enuDataType)
  171. {
  172. filePath.AppendFormat(_T("%s/OriginalOct_%d.bin"), m_strFileDirPath/*, dsr.m_iNum*/,dsr.m_iId);
  173. }
  174. }
  175. }
  176. void AutoMotoDataSaver::SavingThread(void* param)
  177. {
  178. AutoMotoDataSaver* pDataSaver = (AutoMotoDataSaver*)param;
  179. while (pDataSaver->m_bIsThreadOn || (!pDataSaver->m_queueDataInfo.empty()))
  180. {
  181. if (pDataSaver->m_queueDataInfo.size() <= 0)
  182. {
  183. Sleep(50);
  184. continue;
  185. }
  186. CLog::GetInstance()->WriteLog(_T("pDataSaver->m_queueDataInfo.size():%d"),pDataSaver->m_queueDataInfo.size());
  187. DataSaveRequest dsr = pDataSaver->PopDataSaveRequest();
  188. pDataSaver->Save(dsr);
  189. dsr.Release();
  190. }
  191. SetEvent(pDataSaver->m_ExitEvent);
  192. }
  193. void AutoMotoDataSaver::SaveBitmapToFile(DataSaveRequest dsr,CString m_szFileName)
  194. {
  195. /*PUSHORT pBytes,int num*/
  196. //灰度图转换为彩色图
  197. if(dsr.m_pData != NULL)
  198. {
  199. CLog::GetInstance()->WriteLog(_T("保存虹膜图,ProcessFile::SaveBitmapToFile"));
  200. ProcessFile::SaveBitmapToFile(dsr.m_pData, 24,m_szFileName,VEDIOWIDTH, VEDIOHEIGHT);
  201. }else{
  202. CLog::GetInstance()->WriteLog(_T("dsr.m_pData == NULL"));
  203. }
  204. }
  205. }

总结

可以继续把SaveDataInfo和AutoMotoDataSaver采用模板类的方式实现,代码复用性会更高。查阅一下设计模式和模板类相关资料

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/706836
推荐阅读
相关标签
  

闽ICP备14008679号