Win32API ユーザーモード非同期プロシージャ呼び出し QueueUserAPC, WaitForSingleObjectEx

QueueUserAPCにより、FindFirstChangeNotification, FindNextChangeNotificationによるファイルシステムの変更イベントを待機している状態から、無理矢理制御を返すようにする

DWORD WaitForSingleObjectEx(
  HANDLE hHandle,        // オブジェクトのハンドル
  DWORD dwMilliseconds,  // タイムアウト時間
  BOOL bAlertable        // アラート可能な待機のオプション
);


参考:http://msdn.microsoft.com/ja-jp/library/cc429429.aspx


使用するAPI

  • QueueUserAPC

  • WaitForSingleObjectEx

  • FindFirstChangeNotification

  • FindNextChangeNotification

  • FindCloseChangeNotification

  • CreateThread

  • WaitForSingleObject

  • CloseHandle

  • #include <windows.h>
    #include <process.h>
    
    void WINAPI APCFunc(ULONG_PTR arg)
    {
    	printf("APCFunc is called\n");
    }
    
    UINT WINAPI ThreadFunc(LPVOID arg)
    {
    	HANDLE hNotify;
    	DWORD dwFilter;
    	DWORD dwRet;
    
    	//ファイル名の変更イベントを検知するように設定する
    	dwFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
    
    	hNotify = FindFirstChangeNotification(
    		"C:\\", 
    		TRUE, 
    		dwFilter);
    	
    	if (hNotify == INVALID_HANDLE_VALUE) {
    		return 1;
    	}
    
    	do {
    		dwRet = WaitForSingleObjectEx(
    			hNotify, 
    			INFINITE, 
    			TRUE);
    
    		switch (dwRet) {
    			//ファイルシステムの変更イベントにより
    			//WaitForSingleObjectExから制御が
    			//返されると戻り値として
    			//WAIT_OBJECT_0が返される
    			case WAIT_OBJECT_0:
    				puts("WAIT_OBJECT_0");
    				break;
    
    			case WAIT_ABANDONED:
    				puts("WAIT_ABANDONED");
    				break;
    
    			case WAIT_IO_COMPLETION:
    				//QueueUserAPC呼び出しにより、
    				//WaitForSingleObjectExから制御が
    				//返ると、戻り値として 
    				//WAIT_IO_COMPLETION が返される。
    				puts("WAIT_IO_COMPLETION");
    				break;
    
    			case WAIT_TIMEOUT:
    				puts("WAIT_TIMEOUT");
    				break;
    		}
    
    		//QueueUserAPCの呼び出しにより、
    		//WaitForSingleObjectExから制御が
    		//返されたら、ループから脱出する
    		if (dwRet == WAIT_IO_COMPLETION) {
    			break;
    		} 
    
    	} while (FindNextChangeNotification(hNotify));
    
    	FindCloseChangeNotification(hNotify);
    
    	return 0;
    }
    
    int main()
    {
    	HANDLE hThread;
    	UINT uiThreadId;
    
    	//スレッドを起動
    	hThread = (HANDLE)_beginthreadex(NULL,
    		0,
    		ThreadFunc,
    		NULL,
    		0,
    		&uiThreadId);
    
    	Sleep(2000);
    
    	//QueueUserAPCを呼び出すことにより、
    	//ThreadFunc関数中のWaitForSingleObjectExから
    	//制御が返される
    	QueueUserAPC(APCFunc, hThread, 0);
    
    	//スレッドの終了を待つ
    	WaitForSingleObject(hThread, INFINITE);
    
    	//スレッドのハンドルを閉じる
    	CloseHandle(hThread);
    
    	return 0;
    }