Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Delphi: WinAPI и системное программирование > Потоки, файлы и ReadDirectoryChanges |
Автор: dma 29.2.2008, 21:54 | ||
Господа, помогите пожалуйста решить небольшой вопрос. Заключается он в следующем: Есть директория, в которую время от времени "падают" файлы. Состояние директории отслеживается при помощи ReadDirectoryChanges, которая по приходу нового файла говорит FILE_ACTION_ADDED. Есть так же несколько потоков - обработчиков файлов из этой директории. Вообще говоря каждый поток должен брать и обрабатывать файл своей маски, но иногда возникает ситуация, когда несколько потоков берут один и тот же файл (к примеру для них была установлена одинакавая маска, но это не суть). Так вот собственно сам FILE_ACTION_ADDED говорит о том, что файл только создался, а т.к. файл может быть большим, потоку нужно дождаться пока он полностью скопируется. Я реализовал это следующим образом:
Таким образом получается, что когда файл скопируется, то какой-то из потоков его откроет на чтение, а остальные дальше будут ожидать освобождения файла, т.к. не смогут получить к нему доступ. Это хорошо ![]() Буду благодарен за любую помощь. Или за предложение лучшего варианта решения проблемы ![]() |
Автор: bems 29.2.2008, 23:17 |
Вместо TFileStream используй THandleStream. Файл открывай апишкой CreateFile с флагом FILE_FLAG_DELETE_ON_CLOSE и без FILE_SHARE_DELETE |
Автор: dma 1.3.2008, 00:54 | ||
ух ты! Спасибо! То что доктор прописал ![]() Вкратце, получилось так (поправьте, если ошибся):
|
Автор: bems 1.3.2008, 15:04 |
1)убери sleep(10) 2)дескриптор окна и объекта ядра это разные вещи, поэтому вместо hwndF: HWND сделай hFile:THandle, хотя формально это не ошибка 3)FileExists убери. Вместо него в условие until добавь проверку, что если CreateFile вернула INVALID_HANDLE_VALUE, то все равно можно закончить цикл если GetLastError вернула ERROR_FILE_NOT_FOUND или ERROR_PATH_NOT_FOUND. Так и от break избавишся 4)добавь секцию try-finally-end, чтобы убедиться что файл будет закрыт, даже если после его открытия возникло исключение 5) ну и если файл существует но занят, то долбиться в него нужно не бесконечно, а до какого-то предела - вдруг тот кто занял подвис, это же не значит, что вслед за ним должен подвиснуть и ты за компанию. |
Автор: dma 1.3.2008, 23:45 | ||
Снова спасибо за подсказки! ![]() Есть пара вопросов: если Sleep убрать, то этот цикл забьёт весь процесор... а если их ещё и несколько будет, дык вообще вёсла.. в try finally естественно всё это поместиться, я здесь просто рабочий кусок рассматривал ![]() вобщем вышло что-то вроде этого:
кстати, а корректно ли вызывать GetLastError два раза в проверке условия, или же лучше в цикле один раз вызвать и запомнить значение в переменную? |
Автор: dma 2.3.2008, 13:38 | ||
По поводу GetLastErrorCode почитал мануал, сам себе отвечу: вроде как правильнее будет сохранить в переменную сразу после вызова CreateFile.
|
Автор: dma 2.3.2008, 16:06 |
И чужим и моим. Когда поток ждёт, пока файл скопируется - он занят чужим кодом, потом, кода один из потоков захватывает файл, остальные ждут - то моим... |
Автор: bems 2.3.2008, 16:51 |
ну тогда проще длинный слип :( |
Автор: Riply 3.3.2008, 12:13 | ||
Мне казалось, что использование потоков для работы с файлами, расположенными на одном диске, мякго говоря, - искуственное создание "тормозов". ![]() Я ошибаюсь ? P.S. Имеется ввиду именно работа, а не ожидание чего-то. |
Автор: Rennigth 3.3.2008, 12:45 | ||
ну я думаю если реализация с несколькоми(разными) потоками сделана только из-за того что они должны выполнять разные действия с файлами, но паралельное использование нечастое/исключенное, то нормуль ![]() |