首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

浅谈ReadDirectoryChangesW函数的作用和有关问题所在

2012-08-21 
浅谈ReadDirectoryChangesW函数的作用和问题所在转自:http://www.cnblogs.com/yimins/archive/2010/05/18/

浅谈ReadDirectoryChangesW函数的作用和问题所在
转自:http://www.cnblogs.com/yimins/archive/2010/05/18/1738379.html


  这两天又研究了一下ReadDirectoryChangesW函数,下面大致的将研究所得的一些心得体会拿出来和大家分享一下。
  首先这个函数的作用,主要是用于监控某个目录下文件或目录的改动事件。那么究竟这个函数是怎么运作的呢,我打一个比较容易理解的比方给大家。
  我们的应用程序就好比是茫茫大海上一个小小的灯塔,灯塔上有一个观察员(只有一个哦,原因?VB天生的单线程!)ReadDirectoryChangesW函数就好比一副望远镜,观察员的任务有如下三项:
1、通过望远镜观察海上经过的船只(相当于调用主函数进行文件监视)
2、记录下相应的船只名称(处理和记录得到的文件名)
3、和用户聊天。(-_-!!!其实就是负责与用户界面交互)
  由此可见,我们可怜的观察员其实是分身乏术的,尤其是工作3是不能轻易中断的,一旦观察员停止与用户交互,用户第一个反应就是:什么破程序,又卡死了!!!
  有点扯远了,我们言归正传,除聊天之外观察员的正式工作就是盯着望远镜(调用ReadDirectoryChangesW),一旦看到船只经过,立即在纸上抄下船只的名称(记录下被改动的文件名)。这就是ReadDirectoryChangesW函数在同步模式下的工作过程。缺点有两个:1、观察员专心观察,无法和用户聊天。(主窗体失去响应)2、当观察员低下头记录名称的时候,有可能有个别船只会偷偷溜过去。(文件改动事件丢失)
  知道了原因那么解决方式也很简单了,首先我们必须用多线程,再请一个观察员,专门负责盯着望远镜,主线程则负责和用户聊聊天就好了。第二个问题我们采用另一种方法,当观察员见到船只经过的时候,并不进行记录工作,而只是简单的给整个船体拍张照片,然后交给主线程,主线程负责看着照片记录船只名称。因为记录名称的工作并不是非常消耗时间,所以可以在聊天的间隙进行。当然,这样还会带来另一个小小的问题,你的照相机有多少空间,毕竟照相比仅仅记录一个名字要浪费许多空间。
  最后,再解释另一个可能造成丢失事件的原因。由于每次经过的船可能不止一艘,可能会有小船躲在大船后面溜过去,不过这个其实不是问题,因为ReadDirectoryChangesW函数返回的是所有船只的信息,其实是一个链表结构,我们只要顺藤摸瓜将后面的船只也抓出来并进行记录即可。



代码例子:

       //监控主文件夹变化       string dir = "d:\\test\";HANDLE dwRootDirChangeHandle = CreateFileA( dir.c_str(), /* pointer to the file name */FILE_LIST_DIRECTORY,                /* (this is important to be FILE_LIST_DIRECTORY!) access (read-write) mode */FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,  /* (file share write is needed, or else user is not able to rename file while you hold it) share mode */NULL, /* security descriptor */OPEN_EXISTING, /* how to create */FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */NULL /* file with attributes to copy */);if (dwRootDirChangeHandle == INVALID_HANDLE_VALUE){printf("error: %d", GetLastError());return 0;}char notify[1024];memset(notify, 0, 1024);DWORD cbBytes; FILE_NOTIFY_INFORMATION *pNotify=(FILE_NOTIFY_INFORMATION *)notify;char str1[MAX_PATH], str2[MAX_PATH];while ( XSleep(10) ){if(ReadDirectoryChangesW(dwRootDirChangeHandle, &notify, sizeof(notify),FALSE, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_DIR_NAME/*FILE_NOTIFY_CHANGE_LAST_WRITE*/, &cbBytes, NULL, NULL)){int i = 0;memset(str1, 0, MAX_PATH);WideCharToMultiByte( CP_ACP,0,pNotify->FileName, pNotify->FileNameLength/2, str1,99,NULL,NULL );switch(pNotify->Action){case FILE_ACTION_ADDED:printf("New Folder: %s\n", str1);break;case FILE_ACTION_MODIFIED:printf("The file was modified. This can be a change in the time stamp or attributes.\n");break;case FILE_ACTION_REMOVED:printf("The file was removed from the directory.\n");break;case FILE_ACTION_RENAMED_NEW_NAME:printf("The file was renamed and this is the new name.\n");break;case FILE_ACTION_RENAMED_OLD_NAME:printf("The file was renamed and this is the old name.\n");break;default:printf("Unknown command.\n");}// if( 0 != pNotify->NextEntryOffset  && (pNotify->FileNameLength > 0 && pNotify->FileNameLength < MAX_PATH))// {// PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify+pNotify->NextEntryOffset);// memset( str2, 0, sizeof(str2) );// WideCharToMultiByte( CP_ACP,0,p->FileName,p->FileNameLength/2,str2,99,NULL,NULL );// cout << str2 << endl;// }}}::CloseHandle(dwRootDirChangeHandle);

热点排行