In MFC, I added a button in main dialog and ReadDirectoryChangesW function in this button. If the button is clicked, the specified folder will be monitored. The problem is if I clicked button, dialog cannot be worked, because program is still running in ReadDirectoryChangesW function. I want to be able to monitor documents while using the dialog freely, is there any solution?(please refer to code)
void CGGTransferDlg::OnBnClickedAutoStartButton(CString dir)
{
HANDLE dwRootDirChangeHandle = CreateFileA(
dir, /* 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;
}
char notify[1024];
memset(notify, 0, 1024);
DWORD cbBytes;
FILE_NOTIFY_INFORMATION *pNotify = (FILE_NOTIFY_INFORMATION *)notify;
char str1[MAX_PATH];
CString NewResultFileLocal, NewResultFileSever, FileExtension;
while (1)
{
if (ReadDirectoryChangesW(dwRootDirChangeHandle, ¬ify, sizeof(notify),
TRUE, FILE_NOTIFY_CHANGE_FILE_NAME /*| FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE
| FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY*/, &cbBytes, NULL, NULL))//Fourth Parameter = TRUE, Get Subdirectory
{
int i = 0;
memset(str1, 0, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / 2, str1, 99, NULL, NULL);
NewResultFileLocal = str1;//char to cstring
NewResultFileLocal = dir + NewResultFileLocal;
NewResultFileSever = str1;
int n = NewResultFileSever.ReverseFind('\\');
n = NewResultFileSever.GetLength() - n;
NewResultFileSever = NewResultFileSever.Right(n - 1);
FileExtension = PathFindExtension(NewResultFileSever);
if (FileExtension == "aso")
break;
switch (pNotify->Action)
{
case FILE_ACTION_ADDED:
Upload(NewResultFileLocal, NewResultFileSever);
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:
LogSave("The file was removed from the directory: " + NewResultFileLocal);
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");
}
}
}
::CloseHandle(dwRootDirChangeHandle);
}
Your UI doesn't work because you are using
ReadDirectoryChangesW()in a synchronous loop within your UI thread. As such, the UI is blocked from processing other actions. Don't do that.Move your loop to a separate worker thread, and have it notify your main UI as needed whenever a change is detected.
Also, use
ReadDirectoryChangesW()asynchronously so that you can break the loop if you need to terminate the thread, such as during program exit. Create 2 event objects usingCreateEvent(). Put one in anOVERLAPPEDstruct that you give toReadDirectoryChangesW()so it can be signaled whenever a change occurs. Signal the other event manually when you want to terminate the thread. Then you can wait on both events usingWaitForMultipleObjects(), and it will tell you whenever either event is signaled so you can act accordingly.