多线程

互斥量mutex

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

互斥量:

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

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

WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexA(__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,__in     BOOL bInitialOwner,__in_opt LPCSTR lpName);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexW(__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,__in     BOOL bInitialOwner,__in_opt LPCWSTR lpName);
#ifdef UNICODE
#define CreateMutex  CreateMutexW
#else
#define CreateMutex  CreateMutexA
#endif // !UNICODE

参数说明:

lpMutexAttributes:指向安全属性的指针

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

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

创建一个互斥量:

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

事件event

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

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

bManualReset:

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

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

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

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

调用demo

源代码

**.h

#pragma once
#include <vector>
#include <queue>
using namespace std;
class CMySaveData
{
public:CMySaveData(void);~CMySaveData(void);CMySaveData(const CMySaveData& copy);CMySaveData& operator = (const CMySaveData& assign);//光程电机位置int m_opPos;//屈光电机位置int m_refPos;//Z电机位置int m_motoZPos;//图片编号int m_imgNum;
};
enum ENU_DATA_TYPE
{ISO,OCT
};class DataSaveRequest
{
public:DataSaveRequest(ENU_DATA_TYPE enuDataType, CMySaveData mydata);DataSaveRequest();~DataSaveRequest();CMySaveData m_data;ENU_DATA_TYPE m_enuDataType;
};class SaveDataInfo
{
public:SaveDataInfo(void);~SaveDataInfo(void);
private:HANDLE m_Mutex;HANDLE m_ExitEvent;bool m_bIsThreadOn;int m_iSaveCount;  std::queue<DataSaveRequest> m_queueDataInfo;FILE * m_pfile;
private:static void SavingThread(void* param);void Save(const DataSaveRequest& dsr);DataSaveRequest PopDataSaveRequest();void SaveMyData(DataSaveRequest dsr);void PushBackDataSaveRequest(const DataSaveRequest& dsr);
public: void Stop();void SetMyData(CMySaveData myData); void Begin(const CString &strFileDirPath,ENU_DATA_TYPE type);
};

**.cpp

#include "StdAfx.h"
#include "SaveDataInfo.h"
#include <WinBase.h>
DataSaveRequest::DataSaveRequest(ENU_DATA_TYPE enuDataType, CMySaveData mydata):m_enuDataType(enuDataType),m_data(mydata)
{}
DataSaveRequest::DataSaveRequest()
{m_enuDataType=ISO;
}
DataSaveRequest::~DataSaveRequest()
{
}
CMySaveData::CMySaveData(void)
{}
CMySaveData::~CMySaveData(void)
{}
CMySaveData::CMySaveData(const CMySaveData& copy)
{//CLog::GetInstance()->WriteLog(_T("MyLine::MyLine(const MyLine& copy)"));m_refPos=copy.m_refPos;m_motoZPos=copy.m_motoZPos;m_opPos=copy.m_opPos;m_imgNum=copy.m_imgNum;}
CMySaveData& CMySaveData::operator = (const CMySaveData& assign)
{if(this != &assign){m_refPos=assign.m_refPos;m_opPos=assign.m_opPos;m_motoZPos=assign.m_motoZPos;m_imgNum=assign.m_imgNum;}return *this;}SaveDataInfo::SaveDataInfo(void)
{m_bIsThreadOn = false;m_Mutex = CreateMutex(NULL, FALSE, NULL);//ResetEvent手动将事件的状态复原到无信号状态,初始状态没没有信号m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, _T("m_ExitEvent"));
}SaveDataInfo::~SaveDataInfo(void)
{fclose (m_pfile);CloseHandle(m_Mutex);CloseHandle(m_ExitEvent);
}void SaveDataInfo::Begin(const CString &strFileDirPath,ENU_DATA_TYPE type)
{if (m_bIsThreadOn){//如果线程已经创建,直接返回return;}BOOL bIsDirNormal = TRUE;if (!PathIsDirectory(strFileDirPath)){//如果路径不存在创建路径bIsDirNormal = CreateDirectory(strFileDirPath, NULL);}if(!bIsDirNormal){//创建路径失败,直接返回return;}m_iSaveCount = 0;m_bIsThreadOn = true;CString filePath;if (ISO == type){filePath.AppendFormat(_T("%s/ISO_PosInfo.txt"), strFileDirPath);}else if (OCT == type){filePath.AppendFormat(_T("%s/ISO_PosInfo.txt"), strFileDirPath);   }  const size_t strSize=(filePath.GetLength()+1)*2;char* pstr=new char[strSize];size_t sz=0;wcstombs_s(&sz,pstr,strSize,filePath,_TRUNCATE);m_pfile = fopen((const char*)pstr,"w+");//启动保存数据线程_beginthread(SavingThread, 0, this);
}void SaveDataInfo::SavingThread(void* param)
{SaveDataInfo* pDataSaver = (SaveDataInfo*)param;//如果保存线程没有退出,或者保存的数据不为空while (pDataSaver->m_bIsThreadOn || (!pDataSaver->m_queueDataInfo.empty())){if (pDataSaver->m_queueDataInfo.size() <= 0){Sleep(50);continue;}DataSaveRequest dsr = pDataSaver->PopDataSaveRequest();pDataSaver->Save(dsr);}//设置m_ExitEvent为有信号状态,激活m_ExitEventSetEvent(pDataSaver->m_ExitEvent);}
void SaveDataInfo::Stop()
{//设置m_ExitEvent为无信号状态ResetEvent(m_ExitEvent);m_bIsThreadOn = false;//等待m_ExitEvent事件被激活,m_ExitEvent有信号WaitForSingleObject(m_ExitEvent, INFINITE);
}
//取出一个保存请求
DataSaveRequest SaveDataInfo::PopDataSaveRequest()
{DataSaveRequest dsr;WaitForSingleObject(m_Mutex, INFINITE);dsr = m_queueDataInfo.front();m_queueDataInfo.pop();ReleaseMutex(m_Mutex);return dsr;
}
void SaveDataInfo::Save(const DataSaveRequest& dsr)
{       SaveMyData(dsr);}void SaveDataInfo::PushBackDataSaveRequest(const DataSaveRequest& dsr)
{WaitForSingleObject(m_Mutex, INFINITE);m_queueDataInfo.push(dsr);ReleaseMutex(m_Mutex);
}void SaveDataInfo::SetMyData(CMySaveData myData)
{DataSaveRequest dsr(ENU_DATA_TYPE::ISO, myData);   PushBackDataSaveRequest(dsr);
}void SaveDataInfo::SaveMyData(DataSaveRequest dsr)
{CMySaveData tmdata=dsr.m_data;fprintf(m_pfile,"图片编号:%d,\tZ电机位置:%d,\t屈光位置:%d,\t光程位置:%d\n",tmdata.m_imgNum,tmdata.m_motoZPos,tmdata.m_refPos,tmdata.m_opPos);
}

automotodatasaver.h

/************************************************************************/
/* 眼动追踪数据保存(保存追踪过程中的相关数据)                         */
/************************************************************************/
#pragma once
#include <queue>
//#include "ImgPro.h"
//#include "utility.h"
#include "..\..\..\ImgPro.h"
#include "..\..\utility.h"
class CLog;namespace MoptimOct{class AutoMotoDataSaver{private:enum ENU_DATA_TYPE{RegisResult,BaseLso,RegisLso,OriginalOct,Reversed};class DataSaveRequest{public:DataSaveRequest(ENU_DATA_TYPE enuDataType, const PUSHORT pData, int iImageWidth = 0, int iImageHeight = 0);DataSaveRequest();~DataSaveRequest();void Release();BYTE* m_pData;int m_iImageWidth;int m_iImageHeight;size_t m_iDataSize;int m_iId; int m_iNum;ENU_DATA_TYPE m_enuDataType;};CString m_strFileDirPath;std::queue<DataSaveRequest> m_queueDataInfo;HANDLE m_Mutex;bool m_bIsThreadOn;int m_iSaveCount;HANDLE m_ExitEvent;CLog *m_pLog;public:AutoMotoDataSaver();virtual ~AutoMotoDataSaver();void Begin(const CString &strFilePath);void Stop();void SetLsoRegisResultData(const ST_LSO_REGIS_RESULT& stRegisResultData, int iId = 0);void SetBaseLsoData(const PUSHORT pHDLSO, int width=VEDIOWIDTH, int height=VEDIOHEIGHT, int iId = 0,int iNum=0);void SetRegisLsoData(const PUSHORT pSmallLSO, int width=SMALL_LSO_WIDTH, int height=SMALL_LSO_HEIGHT, int iId = 0);void SetOriginalOctData(const PUSHORT pOctOriData, int width, int height, int iId = 0);private:void PushBackDataSaveRequest(const DataSaveRequest& dsr);DataSaveRequest PopDataSaveRequest();void Save(const DataSaveRequest& dsr);void SaveBitmapToFile(DataSaveRequest dsr,CString m_szFileName/*PUSHORT pBytes,int num*/);static void SavingThread(void* param);};
}

automotodatasaver.cpp

#include "stdafx.h"
#include "AutoMotoDataSaver.h"
#include <process.h>
#include <iostream>
#include <fstream>
#include "../../Log.h"
#include "ProcessFile.h"namespace MoptimOct{AutoMotoDataSaver::DataSaveRequest::DataSaveRequest(ENU_DATA_TYPE enuDataType, const PUSHORT pData, int iImageWidth /*= 0*/, int iImageHeight /*= 0*/):m_enuDataType(enuDataType), m_pData(NULL), m_iImageWidth(iImageWidth), m_iImageHeight(iImageHeight),m_iId(0),m_iNum(0){BYTE *pdata = new BYTE[VEDIOWIDTH * VEDIOHEIGHT *3];int k = 0;for(int i = 0;i<VEDIOWIDTH * VEDIOHEIGHT;i++){pdata[k] =(BYTE)pData[i];pdata[k+1] =(BYTE) pData[i];pdata[k+2] = (BYTE)pData[i];k+=3;}m_pData = pdata;}AutoMotoDataSaver::DataSaveRequest::DataSaveRequest():m_enuDataType(RegisResult), m_pData(NULL), m_iImageWidth(0), m_iImageHeight(0),m_iId(0){}AutoMotoDataSaver::DataSaveRequest::~DataSaveRequest(){}void AutoMotoDataSaver::DataSaveRequest::Release(){if(NULL == m_pData){return;}BYTE *pBytes = (BYTE*)m_pData;delete[] pBytes;       m_pData = NULL;}AutoMotoDataSaver::AutoMotoDataSaver():m_bIsThreadOn(false),m_iSaveCount(0),m_pLog(0){m_pLog = CLog::GetInstance();m_Mutex = CreateMutex(NULL, FALSE, NULL);m_ExitEvent = CreateEvent(NULL, TRUE, FALSE, _T("m_ExitEvent"));}AutoMotoDataSaver::~AutoMotoDataSaver(){CloseHandle(m_Mutex);CloseHandle(m_ExitEvent);}void AutoMotoDataSaver::Begin(const CString &strFileDirPath){if (m_bIsThreadOn){CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,if (m_bIsThreadOn)"));return;}BOOL bIsDirNormal = TRUE;if (!PathIsDirectory(strFileDirPath)){CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,if (!PathIsDirectory(strFileDirPath))"));bIsDirNormal = CreateDirectory(strFileDirPath, NULL);}if(!bIsDirNormal){return;}m_iSaveCount = 0;m_strFileDirPath = strFileDirPath;m_bIsThreadOn = true;CLog::GetInstance()->WriteLog(_T("AutoMotoDataSaver::Begin,_beginthread(SavingThread, 0, this);"));_beginthread(SavingThread, 0, this);}void AutoMotoDataSaver::Stop(){ResetEvent(m_ExitEvent);m_bIsThreadOn = false;WaitForSingleObject(m_ExitEvent, INFINITE);}void AutoMotoDataSaver::SetLsoRegisResultData(const ST_LSO_REGIS_RESULT& stRegisResultData, int iId){/*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_REGISRESULT)){return;}DataSaveRequest dsr(AutoMotoDataSaver::RegisResult, (void*)&stRegisResultData);dsr.m_iId = iId;PushBackDataSaveRequest(dsr);*/}void AutoMotoDataSaver::SetBaseLsoData(const PUSHORT pHDLSO, int width, int height, int iId,int iNum){/*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_HDLSO)){return;}*/DataSaveRequest dsr(AutoMotoDataSaver::BaseLso, pHDLSO, width, height);dsr.m_iId = iId;dsr.m_iNum=iNum;PushBackDataSaveRequest(dsr);}void AutoMotoDataSaver::SetRegisLsoData(const PUSHORT pSmallLSO, int width/*=SMALL_LSO_WIDTH*/, int height/*=SMALL_LSO_HEIGHT*/, int iId){/*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_SMALLHDLSO)){return;}*//*DataSaveRequest dsr(AutoMotoDataSaver::RegisLso, (void*)pSmallLSO, width, height);dsr.m_iId = iId;PushBackDataSaveRequest(dsr);*/}void AutoMotoDataSaver::SetOriginalOctData(const PUSHORT pOctOriData, int width, int height, int iId){/*if (!m_pLog->CheckSaveDataMask(LOG_SAVE_TRACING_ORIGINALOCT)){return;}*//*DataSaveRequest dsr(AutoMotoDataSaver::OriginalOct, (void*)pOctOriData, width, height);dsr.m_iId = iId;PushBackDataSaveRequest(dsr);*/}void AutoMotoDataSaver::PushBackDataSaveRequest(const DataSaveRequest& dsr){WaitForSingleObject(m_Mutex, INFINITE);m_queueDataInfo.push(dsr);ReleaseMutex(m_Mutex);}AutoMotoDataSaver::DataSaveRequest AutoMotoDataSaver::PopDataSaveRequest(){DataSaveRequest dsr;WaitForSingleObject(m_Mutex, INFINITE);dsr = m_queueDataInfo.front();m_queueDataInfo.pop();ReleaseMutex(m_Mutex);return dsr;}void AutoMotoDataSaver::Save(const DataSaveRequest& dsr){        CString filePath;if (RegisResult == dsr.m_enuDataType){filePath.AppendFormat(_T("%s/RegisResult.txt"), m_strFileDirPath);ST_LSO_REGIS_RESULT* pRegisResult = (ST_LSO_REGIS_RESULT*)dsr.m_pData;CString strRegisResult;strRegisResult.AppendFormat(_T("ID=%d state=%d xOffset=%lf yOffset=%lf\r\n"), dsr.m_iId, (int)(pRegisResult->state), pRegisResult->xOffset, pRegisResult->yOffset);
#ifdef UNICODEstd::wofstream ofs(filePath, std::ios::out | std::ios::app);ofs << strRegisResult.GetBuffer();
#elsestd::ofstream ofs(filePath, std::ios::out);ofs << strRegisResult;
#endif}else{if (BaseLso == dsr.m_enuDataType){filePath.AppendFormat(_T("%s%d.BMP"), m_strFileDirPath, dsr.m_iNum/*,dsr.m_iId*/);CLog::GetInstance()->WriteLog(_T("保存虹膜图,SaveBitmapToFile,dsr.m_iNum: %d,dsr.m_iId: %d"),dsr.m_iNum,dsr.m_iId);//CLog::GetInstance()->WriteLog(filePath);SaveBitmapToFile(dsr,filePath);}else if(RegisLso == dsr.m_enuDataType){filePath.AppendFormat(_T("%s/RegisLso_%d.bin"), m_strFileDirPath,  /*dsr.m_iNum,*/dsr.m_iId);}else if(OriginalOct == dsr.m_enuDataType){filePath.AppendFormat(_T("%s/OriginalOct_%d.bin"), m_strFileDirPath/*,  dsr.m_iNum*/,dsr.m_iId);}}  }void AutoMotoDataSaver::SavingThread(void* param){AutoMotoDataSaver* pDataSaver = (AutoMotoDataSaver*)param;while (pDataSaver->m_bIsThreadOn || (!pDataSaver->m_queueDataInfo.empty())){if (pDataSaver->m_queueDataInfo.size() <= 0){Sleep(50);continue;}CLog::GetInstance()->WriteLog(_T("pDataSaver->m_queueDataInfo.size():%d"),pDataSaver->m_queueDataInfo.size());DataSaveRequest dsr = pDataSaver->PopDataSaveRequest();pDataSaver->Save(dsr);dsr.Release();}SetEvent(pDataSaver->m_ExitEvent);}void AutoMotoDataSaver::SaveBitmapToFile(DataSaveRequest dsr,CString m_szFileName){/*PUSHORT pBytes,int num*///灰度图转换为彩色图if(dsr.m_pData != NULL){CLog::GetInstance()->WriteLog(_T("保存虹膜图,ProcessFile::SaveBitmapToFile"));ProcessFile::SaveBitmapToFile(dsr.m_pData, 24,m_szFileName,VEDIOWIDTH, VEDIOHEIGHT);}else{CLog::GetInstance()->WriteLog(_T("dsr.m_pData == NULL"));}}}

总结

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

C++创建线程实现自动保存队列中的数据相关推荐

  1. 如何保证 Redis 消息队列中的数据不丢失?

    Redis 最常见的业务场景就是缓存读取与存储,而随着时间的推移,有人开始将它作为消息队列来使用了,并且随着 Redis 版本的发展,在 Redis.2.0.0 中新增了发布订阅模式(Pub/Sub) ...

  2. Flink使用KafkaSource从Kafka消息队列中读取数据

    Flink使用KafkaSource从Kafka消息队列中读取数据 使用KafkaSource从Kafka消息队列中读取数据 1.KafkaSource创建的DataStream是一个并行的DataS ...

  3. 保存ResultSet中的数据(Java Source Code)

    当我们在编写程序的时候,免不了要与数据库打交道,相信ResultSet大家也并不陌生,从数据库读取的数据将会存入其中. 操作结束关闭数据库连接以及ResultSet,否则保持数据库的连接并直接对Res ...

  4. Qt工作笔记-保存textEdit中的数据,并自动打开文件

    功能如标题所示. 程序运行如下: 代码如下: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include & ...

  5. 并发编程02-什么是线程安全以及Java虚拟机中哪些数据是线程共享的,那些是线程私有的

    线程安全的本质 什么是线程安全 要说什么是线程安全,那么我们看看生活中例子吧. 场景1:王菲要来西安体育场开演唱会,这个体育场规模不是很大,能容纳1000个人,于是准备了1000张票,后天中午12点在 ...

  6. php向页面中添加数据_PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码...

    创建文件我们用到函数 fopen ( string filename, string mode ) 参数filename为创建文件名 参数mode为以什么方式打开文件filename 其中mode可能 ...

  7. matlab示波器图形保存,MATLAB中示波器数据的绘图与保存

    一.设置示波器参数 双击示波器:parameters->Data History->Save data to workspace, 此时示波器的相关数据将会以结构体的形式存储,该结构的名字 ...

  8. 删除rabbitmq的队列和队列中的数据

    访问http://{rabbitmq安装IP}:15672,帐号guest,密码guest(也可以使用自己创建的帐号). 登录后访问http://{rabbitmq安装IP}:15672/#/queu ...

  9. java 多线程取一条记录_java多线程从队列中取出数据执行

    天涯尽头无女友 楼上的解释完全正确,不过可以利用s.poll()返回值是否为null,作为跳出条件.下面诗完整代码.packagecom.demo;importjava.util.ArrayList; ...

最新文章

  1. Windows内存的一些知识点
  2. 关于优酷开发SDK之setOnSeekCompleteListener
  3. URL去重的几种方法
  4. 7.4.8 数据压缩
  5. 用C/C++开发《Photoshop》图像处理软件
  6. sudo mysql压缩备份解压操作_高效管理文件之压缩及解压缩 .bz2 文件
  7. 信息学奥赛一本通(1183:病人排队)
  8. DecimalFormat的几种用法!关于字符串的使用
  9. 烤烟发病叶片高光谱特征分析
  10. ip代理服务器8需要云速捷_nginx获取真实ip,proxy_set_head怎么设置头部信息
  11. 折腾Java设计模式之状态模式
  12. python爬取有道翻译的代码_python爬虫之有道翻译
  13. nginx配置错误导致的目录穿越漏洞
  14. 奇偶数排序--整数数组的奇偶数分开(小米公司笔试题)
  15. 《非暴力沟通》读后感
  16. Google 黑客搜索技巧
  17. BeijingSubway
  18. gost备份linux系统,linux系统GOST备份教程.doc
  19. IPC 进程间通讯,排队输出--day33
  20. 首先,打破一切常规 学习笔记 之一

热门文章

  1. xcode怎样分析检测内存泄露(iOS)
  2. CMCC-EDU一个帐号,多设备共享解决方案
  3. HTML学习14:框架布局
  4. 面试总结(三):我的第一次社招之路
  5. 网络质量分析-NQA
  6. 什么是php多线程?
  7. 文件服务器 ldap,windows下搭建ldap服务器
  8. ifree的爱情,是一条完美的九分裤
  9. 去年的烟花特别多……
  10. 帝王封赏之道和老板的封赏之道