フォルダを常時監視しておいて、ファイルが放り込まれたら、
自動的にファイル変換してくれたらよいね。
なんていう話があった。
一週間という短い間に、対象ソフトは別で2件あった。
こいつぁ、なんとかせにゃー!
という意気込みで、調査してみた。
キーワードは、WindowsAPIの以下の関数。
FindFirstChangeNotification( )
「変更通知ハンドルを作成し、変更通知の初期フィルタ条件を設定します。
指定されたディレクトリやサブツリーで変更内容がフィルタ条件と一致すると、
変更通知ハンドルの待機状態が完了します。」(MSDNから引用)
以下の様な、サンプルプログラムを作ってみた。
// フォルダ監視開始
CString path( “c:\\work\\” );
HANDLE hFolder = FindFirstChangeNotification( path, FALSE, FILE_NOTIFY_CHANGE_SIZE );
if( hFolder == INVALID_HANDLE_VALUE ) // 失敗
return;
while(1)
{
DWORD ret = WaitForSingleObject( hFolder, 5000 );
if( ret == WAIT_OBJECT_0 ) // 変更された
{
// データ変換実行
}
else if( ret == WAIT_TIMEOUT ) // タイムアウト
{
if( m_Stop ) // 終了ボタンが押された
break;
}
else // 何やらエラー
break;
if( FindNextChangeNotification( hFolder ) == FALSE ) // 再手続き失敗
break;
}
FindCloseChangeNotification( hFolder );
フォルダ監視処理とデータ変換処理の同期もしっかりとれる。
そして、タイムアウトを5秒としたのがミソだ。
一定時間ごとに終了の合図を確認しておかないと、
while(1)で永久ループになっちまう。
その終了合図は、ユーザーインターフェースから入力させる必要があるので、
スレッドを分けなきゃいけなくなる。
つまり、フォルダ監視処理を AfxBeginThread( )で、別スレッドにする必要があるね。
詳しくは、以前このブログに書いた記事が参考になるだろう。
マルチスレッド
// フォルダ監視終了
if( m_pThread ) // スレッド実行中
{
m_Stop = TRUE;
WaitForSingleObject( m_pThread->m_hThread, INFINITE ); // スレッドが終了するのを待つ
delete m_pThread;
m_pThread = NULL;
}
かねがね思っていたんだよね。
エクスプローラなんかで空のフォルダを表示しているときに、
外部からデータがコピーされたり作成されたりすると、
リアルタイムでポッっと現れるのは、どうやってやってるんだろうと。
どうやら、こんな監視処理をしてるんだな。
スレッドが絡むので、以前はハードルが高かったけど、
今では十分理解できるようになった。
うん、うん、成長したもんだな。
Vistaで64ビットアプリケーションが本格化してきたら、
マルチスレッドは必須のプログラミング技術になるだろうから、
今のうちにマスターしとかなきゃな!