У меня главный поток приложения по нажатию кнопки сначала создает файл для отправки в темповом каталоге, а затем перебрасывае его в общий выходной каталог. И так сразу для нескольких файлов.
Еще есть служебный поток (порожденный от TThread), который через функцию TThread::Synchronize и цикл FindFirstFile/FindNextFile выбирает их оттуда и обрабатывает. Так вот он не всегда цепляет файлы в той последовательности, в которой их подсовывает главный поток. Это заметно когда файлов много и идут они быстро один за другим. Если отправлять файлы по одному, то все нормально.
Кстати я еще замечал интересную фишку. Если в дебаге отлаживаеть цикл FindFirstFile/FindNextFile и в какой-то момент приостановив прогу, выйдти в Far и грохнуть все выбираемые файлы этого каталога, то при возвращении в дебуг в цикле будут цепляться несуществующие файлы!
Это я заметил довольно давно.
Может перед циклом FindFirst/FindNext или где-то внутри него как-то рефрешить информацию о перебираемых файлах, ведь не зря же есть ф-ия SHChangeNotify, которая уведомляет систему об изменениях в файловой системе.
Кто-нибудь знает, как вообще перебирает файлы цикл FindFirstFile/FindNextFile, т.е. в какой последовательности ?
Мне видится,что проблема в следующем. Есть общий каталог, куда кто-то пишет и кто-то читает, так вот порядок записи должен совпадать с порядком считывания.
Как нужно формировать файлы в общем каталоге, чтобы они потом считывались в порядке создания ? И как считывать их правильно ?
У меня сейчас сделано так. Главный поток создает файл в темповом каталоге, затем в общем каталоге создается файл по CreateFile с эксклюзиывным доступом, куда переписывается информация из темпового файла и делается CloseHandle.
Поток выборки использует цикл FindFirstFile/FindNextFile, в котором для каждого найденного файла проверяет эксклюзивный доступ к нему. Если доступа нет — FindClose и цикл начинается сначала.
В твоей ситуации я бы посоветовал FindFirstChangeNotification\FindNextChangeNotification\FindCloseChangeNotification
P>Кто-нибудь знает, как вообще перебирает файлы цикл FindFirstFile/FindNextFile, т.е. в какой последовательности ?
Имхо, на FAT перебирает в том порядке, в котором они идут в таблице, т.е. в той самой FAT
Здравствуйте Pumpr, Вы писали:
P>Я программирую под Builder С++ 6.0.
P>У меня главный поток приложения по нажатию кнопки сначала создает файл для отправки в темповом каталоге, а затем перебрасывае его в общий выходной каталог. И так сразу для нескольких файлов.
P>Еще есть служебный поток (порожденный от TThread), который через функцию TThread::Synchronize и цикл FindFirstFile/FindNextFile выбирает их оттуда и обрабатывает. Так вот он не всегда цепляет файлы в той последовательности, в которой их подсовывает главный поток. Это заметно когда файлов много и идут они быстро один за другим. Если отправлять файлы по одному, то все нормально.
P>Кстати я еще замечал интересную фишку. Если в дебаге отлаживаеть цикл FindFirstFile/FindNextFile и в какой-то момент приостановив прогу, выйдти в Far и грохнуть все выбираемые файлы этого каталога, то при возвращении в дебуг в цикле будут цепляться несуществующие файлы! P>Это я заметил довольно давно.
Интерестно.. Попробую, т.к. сомневаюсь.. Это несколько противоречит тому, что я думал. Под какими ОС наблюдается?
P>Может перед циклом FindFirst/FindNext или где-то внутри него как-то рефрешить информацию о перебираемых файлах, ведь не зря же есть ф-ия SHChangeNotify, которая уведомляет систему об изменениях в файловой системе.
P>Кто-нибудь знает, как вообще перебирает файлы цикл FindFirstFile/FindNextFile, т.е. в какой последовательности ?
Наверное, в той, в которой они в файловой системе.
P>Мне видится,что проблема в следующем. Есть общий каталог, куда кто-то пишет и кто-то читает, так вот порядок записи должен совпадать с порядком считывания.
P>Как нужно формировать файлы в общем каталоге, чтобы они потом считывались в порядке создания ? И как считывать их правильно ?
Использовать какой-то внешний признак. Например, имя файла или время создания. Т.е. сначала получить весь список, а потом его сортировать.
P>У меня сейчас сделано так. Главный поток создает файл в темповом каталоге, затем в общем каталоге создается файл по CreateFile с эксклюзиывным доступом, куда переписывается информация из темпового файла и делается CloseHandle.
P>Поток выборки использует цикл FindFirstFile/FindNextFile, в котором для каждого найденного файла проверяет эксклюзивный доступ к нему. Если доступа нет — FindClose и цикл начинается сначала.
Эти потоки в одном приложении? Тогда что мешает им общаться между собой? Т.е. "главный" сформировал файл и пинает рабочий.. В процессе "пинания" можно передавать имя. А можно вообще без файлов, сразу передавать данные..
Делай что должно, и будь что будет
Re[2]: Проблема с циклом FindFirstFile/FindNextFile
Здравствуйте SergH, Вы писали:
P>>Кстати я еще замечал интересную фишку. Если в дебаге отлаживаеть цикл FindFirstFile/FindNextFile и в какой-то момент приостановив прогу, выйдти в Far и грохнуть все выбираемые файлы этого каталога, то при возвращении в дебуг в цикле будут цепляться несуществующие файлы! SH>Интерестно.. Попробую, т.к. сомневаюсь.. Это несколько противоречит тому, что я думал. Под какими ОС наблюдается?
Под Win2000 железно так работает. Только что проверил, до этого работал на Win98 там тоже так было.
Как это сделать. Под дебагом делаем цикл FindFirstFile/FindNextFile и ставим точку прерывания на то мнесто где находится файл. Копируем откуда-нибудь в этот каталог штук 10 файлов. Получаем остановку. Переходим в Far и удаляем все файлы, кроме найденного. После этого у меня очередной цикл FindNextFile находит файл, которого уже нет. Правда только один, но какая разница ?
P>>У меня сейчас сделано так... SH>Эти потоки в одном приложении? Тогда что мешает им общаться между собой? Т.е. "главный" сформировал файл и пинает рабочий.. В процессе "пинания" можно передавать имя. А можно вообще без файлов, сразу передавать данные..
У меня в одном, но у нас взаимодействуют 2 приложения и мы всегдла полагались на непогрешимость FindFirstFile/FindNextFile в плане последовательности файлов.
Re[2]: Проблема с циклом FindFirstFile/FindNextFile
P>В твоей ситуации я бы посоветовал FindFirstChangeNotification\FindNextChangeNotification\FindCloseChangeNotification
Очень интересно, надо попробовать. Говорят, что были случаи когда файл в каталоге был, а эта связка его не замечала — такое может быть и как с этим бороться ?
И еще. Конструкция FindFirstChangeNotification\FindNextChangeNotification находит файлы в каталоге, если они уже есть ? Т.е. не появились во время работы этих функций, а существовали на диске.
P>>Кто-нибудь знает, как вообще перебирает файлы цикл FindFirstFile/FindNextFile, т.е. в какой последовательности ?
P>Имхо, на FAT перебирает в том порядке, в котором они идут в таблице, т.е. в той самой FAT
Вот и я так думаю.
Re[3]: Проблема с циклом FindFirstFile/FindNextFile
Здравствуйте Pumpr, Вы писали:
P>Под Win2000 железно так работает. Только что проверил, до этого работал на Win98 там тоже так было. P>Как это сделать. Под дебагом делаем цикл FindFirstFile/FindNextFile и ставим точку прерывания на то мнесто где находится файл. Копируем откуда-нибудь в этот каталог штук 10 файлов. Получаем остановку. Переходим в Far и удаляем все файлы, кроме найденного. После этого у меня очередной цикл FindNextFile находит файл, которого уже нет. Правда только один, но какая разница ?
Спасибо за подробное описание, попробую.
P>У меня в одном, но у нас взаимодействуют 2 приложения и мы всегдла полагались на непогрешимость FindFirstFile/FindNextFile в плане последовательности файлов.
Тогда можно так:
1. Рабочий поток крутит следующий цикл:
a) FindFirstFile/FindNextFile для обнаружения всех файлов
b) Как советовал Patalog, ожидание FindNextChangeNotification, когда дождались — goto a)
2. Главный поток делает задержки между отправкой файлов. Я думаю, Sleep(1000) хватит за глаза.
Я думаю, что в Вашем случае лучше отказаться от использования FindFirstFile и FindNextFile.
Взаимодействие между потоками можно организовать следующим образом:
— Если нет острой необходимости в использовании файлов, от них лучше отказаться (производительность++)
— Поток А — формирующий данные; поток Б — их принимающий.
1. Поток Б — содержит очередь данных, подлежащих обработке, в кольцевом списке.
(в случае с файлами — имена файлов, если без них — указатели)
2. Поток Б — должен иметь функции работы с очередью; указатель на начало очереди; указатель на конец очереди.
3. Поток А после подготовки данных (записи их в файл) помещает в очередь потока Б указатель на эти данные (имя файла).
4. Поток Б получает данные из очереди и обрабатывает их.
Думаю, что это поможет.
Завидую людям, которые могут себе позволить никуда не спешить.