Как реализовать запись на винт непрерывного потока данных из внешнего устройства
Подскажите, пожалуйста, как наиболее разумно реализовать следующую задачу:
Есть USB 1.1 устройство, режим Bulk, которое после команды с компа начинает передавать непрерывный поток данных в комп. Скорость передачи информации (ширина потока) ~750 KБ / сек. Оболочка запрашивает данные от драйвера в отдельном потоке блоками по 64 КБ, после чего этот же блок сохраняется в файл. После получения блока устанавливается флажок для основного потока и если предыдущий экран был прорисован то прорисовывается часть данных (2-3%) только что полученного блока (что бы пользователь видел что что-то меняется), если же предыдущий экране не был прорисован, то данные с текущего блока не будут прорисованы, но в любом случае сохраняются в файл. При этом загрузка проца составляет ~20-30 % (Атлон 1700, 512 ОЗУ). Приоритет у потока получения данных TimeCritical, а у оболочки HIGH_PRIORITY_CLASS / THREAD_PRIORITY_TIME_CRITICAL.
Проблема заключается в следующем:
При перемещении или изменении размеров основного окна или просто при нажатии на заголовок окна оболочники происходит довольно ощутимая задержка, что приводит к сбою данных принимаемых в отдельном потоке. Сбой происходит, скорее всего, из-за того, что между запросами к драйверу получается большая пауза ~ 10-20 мс во время манипуляций с основным окном, за эти 10-20 мс USB устройство успевает набить в свое FIFO (5 КБ) 750 * 10-20 = 7500 - 15000 Байт, т.е. происходит переполнение и FIFO и оболочка получает уже всякий бред.
Если же двигать окна любых других программ над оболочкой, запускать тяжелые программы или смотреть фильм, то ни каких глюков нет. Т.е. можно предположить что именно манипуляции с основным окном и приводят чуть ли не к остановке всех потоков приложения?
Подскажите, пожалуйста, как можно сделать, так что бы данные, полученные от устройства всегда были сохранены на винт и следующий запрос происходил максимально быстро, без влияния манипуляций с основным окном? Можно ли как-то запустить чтения данных в другом процессе, например Dll, задача которого просто принять данные и скинуть их на винт?
Например, при прослушивании музыки в WinAmp и перемещении окна проигрывателя звук не искажается, хотя там обработки значительно больше, чем просто принял и сохранил. Может, кто знает, как это реализовано?
Спасибо.
Как реализовать запись на винт непрерывного потока данных
Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Как мне кажется, происходи примерно следующее.
Второй поток заполняет буфер данными, и записывает их на диск.
Главные поток тоже читает эти данные (тот же буфер) для отрисовки на экран.
Во время перетаскивания окна тратится много ресурсов (CPU) в главном потоке.
Возможно, Вы используете синхронизацию потоков.
В этом случае, когда главный поток, занятый перетаскиваеним окна
начинает медленно читать данные буфера, второй поток (в силу синхронизации)
ждет входа в CriticalSection. А данные оказываются уже упущенными.
Т.е. главный поток входит в CriticalSection и начинает тормозить (Так как Windows сугубо для этого потока делает ВАЖНУЮ работу по поддержке GUI). А первый конкурирует с главным за буфер - ждет, когда его пустят в CriticalSection.
Это лишь предположение. Точнее можно сказать только если посмотреть исходники.
Если я прав.... То, что делать?
Теоретически, так как данные нужны только для того, чтобы пользователь видел что они есть (а не что они содержат), то здесь можно положить на синхронизацию.
Ну и пускай, данные, которые главный поток отображает на нэкране будут "испорчены" другим потоком. В данном случае это не существенно.
Другое решение иметь еще один (третий) поток, тянущий данные буфера во второй буфер. Пусть этот третий поток тянет столько, сколько успеет, он будет конкурировать за основной буфер с первым потоком непродолжительное время, но большее время будет простаивать при входе в другую CriticalSection, при конкурировании с главным потоком за второй (дополнительный) буфер.
Главный поток будет будет "съедать" столько данный, сколько ему "скормит" второй поток.
Второй поток заполняет буфер данными, и записывает их на диск.
Главные поток тоже читает эти данные (тот же буфер) для отрисовки на экран.
Во время перетаскивания окна тратится много ресурсов (CPU) в главном потоке.
Возможно, Вы используете синхронизацию потоков.
В этом случае, когда главный поток, занятый перетаскиваеним окна
начинает медленно читать данные буфера, второй поток (в силу синхронизации)
ждет входа в CriticalSection. А данные оказываются уже упущенными.
Т.е. главный поток входит в CriticalSection и начинает тормозить (Так как Windows сугубо для этого потока делает ВАЖНУЮ работу по поддержке GUI). А первый конкурирует с главным за буфер - ждет, когда его пустят в CriticalSection.
Это лишь предположение. Точнее можно сказать только если посмотреть исходники.
Если я прав.... То, что делать?
Теоретически, так как данные нужны только для того, чтобы пользователь видел что они есть (а не что они содержат), то здесь можно положить на синхронизацию.
Ну и пускай, данные, которые главный поток отображает на нэкране будут "испорчены" другим потоком. В данном случае это не существенно.
Другое решение иметь еще один (третий) поток, тянущий данные буфера во второй буфер. Пусть этот третий поток тянет столько, сколько успеет, он будет конкурировать за основной буфер с первым потоком непродолжительное время, но большее время будет простаивать при входе в другую CriticalSection, при конкурировании с главным потоком за второй (дополнительный) буфер.
Главный поток будет будет "съедать" столько данный, сколько ему "скормит" второй поток.