Archive for September 4th, 2005

文件实时监控

  我们的软件中需要对特定的文件夹进行监控,当数据文件的内容发生变化都需要发送一个消息通知上层的业务处理对象。VC中不像.NET那样可以轻松的创建一个FileSystemWatcher对象,但是一个VC程序员也应该能够很轻松的实现这样的功能。

  首先查找MSDN,立刻就在File I/O Function中找到了如下一组API:

HANDLE FindFirstChangeNotification(
 LPCTSTR lpPathName,
 BOOL bWatchSubtree,
 DWORD dwNotifyFilter
);

BOOL FindNextChangeNotification(
 HANDLE hChangeHandle
);

BOOL FindCloseChangeNotification(
 HANDLE hChangeHandle
);

  并且提供了一段使用样例(后来在网上发现的大部分资源其实也就是把这个例子翻译修改了一下),编译运行后发现基本上符合我的需要,只是有一点让我感觉到很奇怪。在调用第二个函数的时候,重新开始循环,在WaitForMultipleObject处直接pass过去,这样一次修改数据就会两次触发,这让我有点疑惑。

  接下来的事情就简单多了,从CWinThread类派生一个CFileMonitor类,提供几个自定义消息:启动、暂停、关闭、通知,并且创建几个Event事件,线程类接收到启动消息后启动一个工作线程,通过对Find***ChangeNotify和WaitFor***Object等函数实现对文件夹的监控。

  类的定义基本如下:

class CFileMonitor : public CWinThread
{
 DECLARE_DYNCREATE(CFileMonitor)
protected:
 CFileMonitor();
public:
 void SetPath(LPCTSTR lpszPath);
 void SetHwnd(HWND hWnd);
protected:
 // 消息处理函数
 // 前三者由调用者发给监控类
 // 最后一个由工作线程函数发给监控类
 afx_msg void OnMonitorStart(WPARAM, LPARAM);
 afx_msg void OnMonitorPause(WPARAM, LPARAM);
 afx_msg void OnMonitorClose(WPARAM, LPARAM);
 afx_msg void OnCallBack(WPARAM, LPARAM);
protected:
 // 工作线程函数
 static UINT StartMonitor(LPVOID lpParam);
 CString  m_strPath;
 HWND  m_hWnd;

 HANDLE  m_hStart;
 HANDLE  m_hPause;
 HANDLE  m_hClose;
};

  关键是工作线程函数,这里我把工作线程函数写成了类自己的一个static成员函数。函数内部基本上就是一个While循环,直到发生错误或者接收到关闭消息才退出循环,如果待监控的文件夹发生变化则向监控类抛出一个消息,由监控类根据需要转发给外部,然后进行下一次的循环。

  监控类自己的几个消息处理函数相对简单很多,无非就是设置一下事件状态,或者把消息转发给监控的调用者,如果是错误或者关闭消息,还要负责调用一下PostQuitMessage函数以退出线程。

  监控类的调用者只需要定义一个CFileMonitor指针做为私有成员,在构造函数中启动这个线程类,设置一下需要监控的目录和接受通知消息的句柄,然后根据需要发送消息通知监控类器动或者暂停,并且添加一个消息响应函数用于处理WM_FILEMON_NOTIFY消息即可。当然,别忘了在调用者本身被销毁之前,要发送一个关闭消息给监控类,否则一来监控无法关闭,而且也将产生内存泄漏。

  范例如下:

CFileMonitor *pMonitor =
 AfxBeginThread(RUNTIME_CLASS(CFileMonitor);
if (pMonitor != NULL)
{
 pFileMonitor->SetPath(_T("D:\Data\"));
 pFileMonitor->SetHwnd(GetSafeHwnd());
 DWORD dwID = pMonitor->m_nThreadID;
 ::PostThreadMessage(dwID, WM_FILEMON_START, 0, 0);
 ……
 ::PostThreadMessage(dwID, WM_FILEMON_CLOSE, 0, 0);
}

  说明:我的一个朋友批评我的日志什么废话都有,就是不像一个软件行业人员。那么我以后就不定期写一些与我的本职工作相关的东西吧,当然不要期望这样的东西有太高技术含量,就当是给自己的进步留下点记号吧。

  

Advertisements

5 Comments

周六流水账

  A.没福睡懒觉
  周末,本来可以是睡懒觉的时候,但是大部分周末,我都会在8点钟之前醒来并且精神状态良好,无法继续入睡。于是一个人搬个椅子蹲在电视机前看片,花近4个小时看完《乱世佳人》,看完已经到了12点多,中途燕子起床一起吃了碗面条。于是我们的周末就从中午正式开始。
  B.光脚逛超市
  分工合作完成家里的一些清扫工作,下午去超市采购。结果走到半路,我脚上踩的拖鞋意外的结束了使命。好在离超市不远,只有小心翼翼的高一脚低一脚择路而行,采购单上也意外的多了一个item。
  进了超市,才发现自己的形象真的有些不搭调:胖子、衬衫、沙滩裤……还有一双赤脚。我们开玩笑说燕子得和我保持距离,否则有损形象。
  一个半小时后,终于可以穿上鞋了。本人的第一次光脚逛超市的壮举也随之宣告结束,不过不知道这是好又多凌云路店历史上的第几位光脚顾客。
  C.诡异的《七剑》
  从超市采购了一些熟食,一边观看传说中徐克花费了一亿四千万的《七剑》一边吃饭。第一个镜头,我开始怀疑自己拿错了光盘,这造型这服装,明明是亚瑟王或者角斗士嘛,咱们中国人什么时候穿过这种铠甲。看到最后一个镜头,我仍然没有记住天山四大弟子中的老三老四叫什么,只知道其中一个似乎头上顶了半个足球,还是手工缝制的。燕子说看得蛮郁闷,我一边往嘴里扒饭,一边平静的说:先看完吧。潜台词是:看在掏了钱的份上,先顶住。
 

3 Comments