一个多线程的日志记录DLL
日志记录对于应用程序来说是很重要的。本文就简单实现的实现了这样一个模块。该模块实现对程序预期的信息进行记录的功能。该模块为每一个向它进行注册的模块开启一个线程并同时创建或者打开一个同名但扩展名为.log的文本文件,此文件位于程序可执行文件目录下的/Log子目录下。这样也具有了一定的灵活性,比如可以再Debug版本中用此库输出调试信息到文件,而在Release版本中真正用于记录日志信息。
下面对其中的两个类的接口介绍一下:
CInfoReport:
该类在实现时已经用AFX_EXT_CLASS关键字指明,是一个DLL导出类,继承自CObject。
数据成员:
// 存放线程的指针链表,所有对象公用一份,故声明为static
static CPtrList m_lstpThreads;
成员函数:
// 注册模块
DWORD Register(LPCTSTR ModuleNameToReg);
// 写入信息,其中的第一个参数MoudleID必须是Register函数的返回值,如果为NULL则将信息记录到FatalErr.log文件中。
void WriteInfo(DWORD MoudleID, CString InfoDescribe);
// 写入信息,其中的第一个参数MoudleID必须是Register函数的返回值,如果为NULL则将信息记录到FatalErr.log文件中。
void WriteInfo(DWORD MoudleID, CString InfoFrom, CString InfoDescribe);
CWriteInfo:
该类继承自CWinThread,用于为每一个已注册的模块开启一个线程并且维护一个扩展名为log的日志文件。因为可能有多个线程同时进行同一文件操作,故此类还提供了互斥机制来确保文件I/O无冲突的进行。
数据成员:
// 注册的模块名,日志文件与它同名但扩展名不同
CString m_strModuleName;
CFile m_file; // 日志文件对象
// 为实现文件互斥操作的事件句柄
HANDLE m_hEventBusy;
成员函数:
// GetName()和SetModuleFileName()对私有成员m_strModuleName进行存取。
CString GetName();
void SetModuleFileName(CString strFileName);
消息处理函数:
// 处理由CInfoReport::WriteInfo()发来的消息TM_WRITE_INFO
afx_msg void OnWriteInfo(WPARAM wParam, LPARAM lParam);
注:未尽事项请参考源代码,包括库本身以及一个测试程序InfoReportTest。简单起见,测试程序(一个文档/视的SDI程序)的视图类的OnDraw()函数里调用了该库的日志记录函数。
程序需要完善的地方
该程序在匆忙之间完成,还有问题没有解决:
1. 安全性检查,比如可执行文件的目录下没有/Log子目录,程序将产生异常。
2. 该程序的导出类在EXE文件中被作为全局变量没有问题,而在DLL中作为全局变量应用则会导致没有反应,跟踪发现是由于创建新线程时在::WaitForSingleObject()处僵死,作为局部变量(类的成员变量使用则没有问题)。
本文属于转载自vc知识库,特此声明。