Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

ReadDirectoryChangesW() под нагрузкой

278
02 мая 2011 года
Alexander92
1.1K / / 04.08.2008
Всем доброго времени суток.
Возник вопрос по сабжу. До последнего не хотел сюда постить, но в конце концов решил спросить хотя бы, кто что думает.

Ситуация следующая. Есть приложение, которое мониторит несколько каталогов с помощью ReadDirectoryChangesW(). Каждому каталогу выделен отдельный поток следующей структуры:
Код:
DWORD WINAPI StartMonitoringDirectory(HANDLE hDirectory) {
  DWORD dwBytesRead = 0, dwWaitState = 0;
  OVERLAPPED overlapped = {0};

  HANDLE hCloseRequestEvent = ....; // запрос на прерывание мониторинга
  HANDLE hSuspendRequestEvent = ....; // запрос на паузу мониторинга
  HANDLE hSuspendedEvent = ....; // мониторинг приостановлен
  HANDLE hResumeRequestEvent = ....; // запрос на восстановление мониторинга
  HANDLE hResumedEvent = ....; // мониторинг восстановлен

  HANDLES hEventsToWait[4] = {hCloseRequestEvent, hSuspendRequestEvent, hResumeRequestEvent, (HANDLE)NULL};

  while (true) {
    ZeroMemory(&overlapped, sizeof(OVERLAPPED));
    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // асинхронное чтение
    hEventsToWait[3] = overlapped.hEvent;
    if (WaitForSingleObject(hSuspendedEvent, 0) != WAIT_OBJECT_0) // если мониторинг не приостановлен
      ReadDirectoryChangesW(hDirectory, lpBuffer, READ_CHANGES_BUF_SIZE, FALSE, FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytesRead, &overlapped, NULL);

     dwWaitState = WaitForMultipleObject(4, hEventsToWait, FALSE /* ждать хотя бы одного события */, INFINITE);
     switch(dwWaitState) {
       case WAIT_OBJECT_0:   // запрос на закрытие
          CloseHandle(overlapped.hEvent);
          ExitThread(0);
          return;

        case WAIT_OBJECT_0 + 1: // запрос на приостановку
           ResetEvent(hSuspendRequestEvent);
           ResetEvent(hResumeRequestEvent);
           ResetEvent(hResumedEvent);
           SetEvent(hSuspendedEvent);

        case WAIT_OBJECT_0 + 2: // запрос на восстановление
           ResetEvent(hResumeRequestEvent);
           ResetEvent(hSuspendRequestEvent);
           ResetEvent(hSuspendedEvent);
           SetEvent(hResumedEvent);
           break;

        case WAIT_OBJECT_0 + 3: // уведомление об изменение в каталоге
           // обработать
           break;

         default:
          CloseHandle(overlapped.hEvent);
          ExitThread(1);
     }
     CloseHandle(overlapped.hEvent);
  }
}

Приведенная конструкция работает правильно, но когда файлы в каталоге меняются сравнительно быстро, происходят какие-то совершенно непонятные "подвисания" на этапе обработки. Сталкивался ли кто-нибудь с особенностями работы ReadDirectoryChangesW() под нагрузкой? Или мне идти и лучше искать свой косяк?
342
04 мая 2011 года
Yos
209 / / 21.06.2003
Буфер, который передается для возврата данных об изменениях какого размера? И не много ли евентов? у меня в одном проекте 256К и всего 2 евента - 1 для ридера и 1 для управления работой, так как логика работы описана по другому и мониторя весь C: никаких проблем с подвисаниями и пропусками не обнаружено, даже на слабых машинах...
278
04 мая 2011 года
Alexander92
1.1K / / 04.08.2008
Дело в том, что эта проблема возникает даже в случае, когда я фиксирую изменения только одного файла в одном каталоге (соответственно, работает два потока - один основной и один монитор), там не больше 4 евентов создается. Я подчеркиваю, проблема возникает только под существенной нагрузкой (например, пишу что-то в файл каждую миллисекунду).

А будут какие-то предложения по общей логике работы? Повторюсь, я допускаю, что это мой баг, но пока категорически не вижу возможных мест его возникновения.
342
04 мая 2011 года
Yos
209 / / 21.06.2003
В вашей логике проблем нет, если она работает со скоростью чтения ее глазами, но... WaitForMultipleObject сама по себе "медленная" функция + процесс переключения потоков по отработке эвентов и отражение этого в планировщике ресурсов влияет (как ни странно) на скорость работы и выделения времени для каждого потока...

Я замечал подобное на стадии изучения этих механизмов, по этому когда писал то, о чем говорил ранее, сделал именно так - 1 поток на весь диск без ограничения по составу и отработка инфы на предмет анализа - этот файл мне интересен или нет...
278
04 мая 2011 года
Alexander92
1.1K / / 04.08.2008
Ну вот я грешу как раз на внутрисистемные особенности, потому что других проблем я пока не вижу.

[QUOTE=Yos]
по этому когда писал то, о чем говорил ранее, сделал именно так - 1 поток на весь диск без ограничения по составу и отработка инфы на предмет анализа - этот файл мне интересен или нет...
[/QUOTE]
К сожалению, в моем случае просто так сделать не получится, потому что мониторятся файлы с разных дисков и с разных компьютеров, которые могут (в принципе) обновляться достаточно быстро. Соответственно, проверять каждый изменившийся файл на "интересность" - довольно дорогое удовольствие в рамках моей задачи.
У меня буквально полчаса назад появилась другая идея: можно попытаться для каждого файла, который подлежит мониторингу, создавать ярлык в некоей временной папке и мониторить только эту одну папку. Проблема здесь в том, что lnk-файл ярлыка, по идее, не изменяется при изменении того файла, на который он ссылается, но это я еще посмотрю поподробнее.

P.S. Пока включил просто перехват изменения последнего времени модификации файла по таймеру, работает нормально.
63K
05 мая 2011 года
SimSonic
16 / / 14.03.2011
lnk-файл имхо глупость, уж лучше тогда hardlink.
278
05 мая 2011 года
Alexander92
1.1K / / 04.08.2008
Да, разумеется, с симлинком я дал маху. Конечно, hardlink лучше, тут без вопросов.
41K
05 мая 2011 года
kisssko
108 / / 28.10.2010
Цитата: Alexander92
Да, разумеется, с симлинком я дал маху. Конечно, hardlink лучше, тут без вопросов.



lnk-файл, это никаким боком не симлинк, а обычный файл, который виндовый шелл обрабатывает.
А, собственно, симлинки на NTFS можно создавать только к папкам.

278
05 мая 2011 года
Alexander92
1.1K / / 04.08.2008
kissko, я понимаю это все. Прошу прощения за неточную терминологию.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог