Как сломать функцию ReadDirectoryChangesW в MF C? - PullRequest
1 голос
/ 24 февраля 2020

В MF C я добавил кнопку в главном диалоге и функцию ReadDirectoryChangesW в этой кнопке. Если кнопка нажата, указанная папка будет отслеживаться. Проблема в том, что если я нажал кнопку, диалоговое окно не может работать, потому что программа все еще работает в функции ReadDirectoryChangesW. Я хочу иметь возможность контролировать документы при использовании диалогов свободно, есть ли какое-либо решение? (Пожалуйста, обратитесь к коду)

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, &notify, 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);
}

1 Ответ

2 голосов
/ 24 февраля 2020

Ваш пользовательский интерфейс не работает, потому что вы используете ReadDirectoryChangesW() в синхронном l oop в вашем потоке пользовательского интерфейса. Таким образом, пользовательский интерфейс заблокирован от обработки других действий. Не делайте этого.

Переместите ваш l oop в отдельный рабочий поток, и он должен уведомлять ваш основной пользовательский интерфейс по мере необходимости при обнаружении изменения.

Также используйте ReadDirectoryChangesW() асинхронно , так что вы можете разорвать l oop, если вам нужно завершить поток, например, во время выхода из программы. Создайте 2 объекта события, используя CreateEvent(). Поместите один в OVERLAPPED структуру, которую вы даете ReadDirectoryChangesW(), чтобы он мог сигнализироваться всякий раз, когда происходит изменение. Сигнализируйте другое событие вручную, когда вы хотите прекратить поток. Затем вы можете дождаться обоих событий, используя WaitForMultipleObjects(), и он будет сообщать вам о каждом событии, сигнализирующем, чтобы вы могли действовать соответственно.

...