![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
В общем, есть приложение, которое записывает данные в файлы(много их) асинхронно, время от времени оно выдает сообщение об ошибке: "The I/O operation has been aborted because of either a thread exit or an application request" и продолжает работать дальше...
К чему-бы это? |
|||
|
||||
| GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 2 Всего: 26 |
к отладчику?
|
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
я не могу это воспроизвести, это происходит после нескольких суток работы приложения, поэтому я и спрашиваю, что может вызвать подобную ошибку (GetLastError = 995)
|
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: нет Всего: 59 |
Мне так кажется не проверяется результат команды записи в файл. Если при неблагоприятном стечении обстоятельств запись в файл задержалась, а поток прекратил работу (считая, что все записал) будет эта ошибка, насколько я понял.
|
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 5 Всего: 211 |
Lazin
Может быть вызвано неправильной синхронизацией потоков. Это ошибка вроде означает что программа пытается прочитать из файла, который закрыт (или может заблокирован??). |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 7 Всего: 459 |
Хотелось бы сначала выяснить могут ли в этой программе 2 потока обращаться к одному файлу.
Еще такое предположение, если событие редкое может файл блокируется антивирусом или службой индексирования? -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
файлы открываются в режиме FILE_SHARE_READ | FILE_SHARE_WRITE а так-же FILE_FLAG_OVERLAPPED
разные потоки могут вызывать WriteFile для одного и того-же файла, данные которые должны быть записаны, удаляются после того, как на порт завершения будет добавлен пакет завершения сигнализирующий о том, что все данные записаны |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
по-русски, 995 ошибка звучит так: "Операция ввода/вывода была прервана из-за завершения потока команд или по запросу приложения. "
Lazin, у тебя ни где не вызывается случайно CancelIO? это по-моему, как раз второй случай - "...по запросу приложения" -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
может-ли такое произойти, поток вызывает WriteFile для асинхронной записи данных, сразу после этого другой поток, или этот-же вызывает TerminateThread? Просто в этом приложении моя только библиотека, которая выполняет файловые операции, что там происходит для меня загадка. |
|||
|
||||
| xvr |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 40 Всего: 223 |
Да
|
||||
|
|||||
| GremlinProg |
|
||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
а принципе - да, если очередь не пуста, а поток завершается, то оставшиеся команды I/O теряются, но по идее, чтобы отловить эту ошибку нужен по крайней мере не полная асинхронная операция, ты используешь простой или расширенный интерфейс? WriteFile или WriteFileEx? у меня есть два варианта возможного решения: 1. в Red/WriteFile а четвертый параметр передавать NULL (это в некотором роде подсказка оси, что в данный момент даже пытаться выполнять операцию не надо) 2. использовать расширенный интерфейс и ввести счетчик операций, тогда перед завершением потока можно убедиться, что очередь не пуста и подождать, если это не так:
а в callback'е завершения I/O, уменьшать этот счетчик:
тогда перед самой чтением/записью, этот счетчик увеличить:
Добавлено через 6 минут и 46 секунд можно синхронный счетчик использовать InterlockedIncrement/Decrement -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
||||||||
|
|||||||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
ошибку я получаю в своей библиотеке все работает примерно так:
это что-то вроде псевдокода, но суть должна быть понятна Добавлено @ 14:42 зы я там использую порт завершения Добавлено @ 14:48 я пока вижу такое решение: не вызывать ф-ю WriteFile из потока пользователя вообще, вместо этого вызывать PostQueuedCompletionStatus и передавать туда данные, приняв которые, мой поток начал-бы выгребать данные из очереди и писать их в файл Это сообщение отредактировал(а) Lazin - 16.4.2009, 14:58 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
а что мешает сначала заполнить очередь,
а потом подождать завершения всех операций? у тебя получается так, что скорость передачи данных в порт напрямую зависит от времени ожидания GetQueuedCompletionStatus и практически не зависит от скорости поступления данных (не используется разрешающая способность самой очереди ввода/вывода) попробуй разделить: если есть данные в очереди - пиши их в порт кончились - жди завершения операций появились - снова пиши и т.д. а принудительно уходи в ожидание только при отказе WriteFile, когда квота заканчивается -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
мне нужно, что-бы даннве по возможности не накапливались в памяти я возможно плохо все описал, попробую исправиться) у меня есть очередь, очередь состоит из буферов фикс. размера, скажем, 64кб пользовательское приложение вызывает ф-ю моей библиотеки, эта ф-я дописывает данные в конец последнего буфера в очереди, если его нет, то она его создает, далее, если в данные момент нет не завершенных операций записи в файл, она начинает новую, вызывая WriteFile. Соответственно в ф-ю WriteFile передаются все 64kb (первый в очереди буфер). В этот момент данные еще не записаны, если пользовательское приложение снова вызовет мою ф-ю, то данные будут добавлены в буфер, но ф-я WriteFile вызвана не будет, так-как предидущая операция записи еще не завершена, считается что он "занят". Рабочий поток моей библиотеки ждет на порте завершения, и когда завершается очередная операция записи он освобождает 64кб буфер, а затем пытается извлечь из очереди следующий буфер и начать записывать его. Пока есть незавершенные операции записи (это контролируется) файл не будет закрыт. Единственное что у меня может пойти не так, это поток пользовательского приложения может начать операцию записи(вызвав WriteFile) и сразу завершиться (вполне вероятно что даже аварийно, вызвав ExitThread или TerminateThread... Это сообщение отредактировал(а) Lazin - 16.4.2009, 22:57 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
нет, я все понял, наверное, сам неверно выразился, смешав 2 очереди ) главное, что я выделяю - это то, что асинхронной ввод/вывод уже имеет очередь, которую можно и даже нужно задействовать, иначе - зачем его вообще использовать? запись в файл при таком раскладе можно осуществлять и синхронно прямо в твоем потоке, ничего от этого не изменится мне кажется, что очередь, которую ты строишь дополнительно - лишняя нагрузка на my_class :: function, если ты хотел отвязаться от ожидания завершения записи на диск при вызове function, то ты от него избавился, но прибавил в нагрузку практически тот же самый вес, формируя дополнительную очередь тут достаточно просто асинхронно писать в файл, учитывая общее число байт (чтобы не выйти из потока преждевременно) достаточно дополнить интерфейс библиотеки функцией flush, в которой просто подождать завершения всех операций (неважно каким способом) поток - нужен, но только на стороне пользователя (как я понял, он там уже есть) если flush невозможно встроить на стороне пользователя, то его можно вызвать в DllMain, перед отсоединением потока тогда ошибок быть не должно -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |