파일 변경 공지 (File Change Notification)
이 장(17장) 초기에, ::WaitForSingleObject 에 전달되는 HANDLE 파라미터가 파일 변경 공지 핸들이 될 수 있다고 언급하였다. Win32 API는 ::FindFirstChangeNotification 이라는 함수를 포함한다. 이 함수는 지정한 디렉토리 또는 그 하위 디렉토리내에서 변경이 일어날 때마다 블락된 쓰레드를 깨우기 위해 사용할 수 있는 핸들을 반환한다 – 예를 들어, 파일의 이름이 변경되었거나, 파일이 삭제되었거나, 새로운 디렉토리가 생성되었다든지.
파일 시스템의 변경이 왼쪽 또는 오른쪽 창에 즉시 반영되도록 하는 기능을 11장의 Wanderer 애플리케이션에 추가하길 원한다고 하자. 그것을 하기 위한 가장 효과적인 방법은 백그라운드 쓰레드를 시작하고 그 쓰레드가 하나 이상의 파일 변경 공지 핸들에 블락되게 하는 것이다. C 드라이브를 모니터하는 쓰레드를 위한 쓰레드 함수는 아래와 같다.
UINT ThreadFunc (LPVOID pParam) { HWND hwnd = (HWND) pParam; // Window to notify HANDLE hChange = ::FindFirstChangeNotification (_T ("C:\\"), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME ¦ FILE_NOTIFY_CHANGE_DIR_NAME); if (hChange == INVALID_HANDLE_VALUE) { TRACE (_T ("Error: FindFirstChangeNotification failed\n")); return (UINT) -1; } while (...) { ::WaitForSingleObject (hChange, INFINITE); ::PostMessage (hwnd, WM_USER_CHANGE_NOTIFY, 0, 2); ::FindNextChangeNotification (hChange); // Reset } ::FindCloseChangeNotification (hChange); return 0; } |
::FindFirstChangeNotification 에 전달되는 첫 번째 파라미터는 모니터하고자 하는 디렉토리를 나타낸다. 두 번째는 디렉토리 자체만(FALSE) 또는 그 디렉토리와 하위 디렉토리(TRUE)까지 모니터할 지를 명시한다. 그리고 세 번째는 쓰레드에 공지되어야 하는 변경의 종류를 나타낸다. 이 예제에서는, C: 드라이브의 어딘가에서 파일이 생성될 때, 이름이 변경될 때, 지워 질 때 (FILE_NOTIFY_CHANGE_FILE_NAME) 또는 디렉토리가 생성될 때, 이름이 변경될 때, 지워질 때(FILE_NOTIFY_CHANGE_DIR_NAME)에 쓰레드가 깨어 날 것이다. 쓰레드가 깨어날 때, 윈도우에 사용자 정의 메시지를 포스트하고 그 메시지의 pParam에 파일 핸들이 전달된다. 메시지의 lParam 은 드라이브 수 ( C: 드라이브는 2)를 나타낸다. 메시지를 받은 윈도우는 – 아마 애플리케이션의 top-level 프레임 윈도우 – 뷰를 업데이트함으로써 그 메시지에 반응할 수 있다. 파일 변경 공지에 의해 깨어난 쓰레드는 변경의 근원에 관해서 또는 디렉토리 트리내에서 변경이 일어난 곳이 어디인지에 관한 정보는 얻을 수 없다는 것을 기억하라, 그래서 파일 변경 공지가 야기된 곳을 찾길 원한다면 파일 시스템을 스캔해야만 한다.
쓰레드가 하나의 드라이브 뿐만 아니라 여러 개를 모니터하도록 만들수도 있다. 해야 하는 모든 작업은 각 드라이브마다 각각의 파일 변경 공지 핸들을 얻기 위해 드라이브마다 ::FindFirstChangeNotification 을 호출하고 동시에 모든 파일 변경 공지에 대해 블락되도록 ::WaitForMultipleObjects 를 사용하는 것이다. ::WaitForMultipleObjects 는 CMultiLock::Lock 과 같은 Win32 API 이다. 세 번째 파라미터에 FALSE 를 전달하는 것은 쓰레드를 블락하고 있는 객체들 중 하나라도 신호상태가 되었을 때 쓰레드가 깨어날 것이라고 시스템에게 말하는 것이다.
참고 : Programming with MFC 2nd Edition