А гораздо лучше работает новый вариант - с двумя потоками (через
vbCreateThread от TheTrick).
Ибо пока он читал новый кадр из камеры (а в темноте у неё выдержка до полусекунды!), программа торчала на месте.
А теперь - смотрите: кадр висит один и тот же (пока-а-а он там новый кадр назначит), а главный поток занимается вращением спрайта, за счёт чего вращение происходит более гладко. А когда я и масштабирование спрайта перенёс туда же в поток, где считывание кадра, а главному потоку осталось лишь наложить два готовых спрайта с вращением, он стал крутиться вообще гладко-гладко и на мышь откликаться мгновенно:
Веб-камера в отдельном потоке.zip
При запуске выбираем вариант: полноценные ДВА потока либо ОДИН (по Таймеру с формы). Разница ошеломительна! (200 FPS против 20 в нормальных условиях, в темноте ещё разительней.)
Кстати, тут двухпоточность реализована без маршалинга, а с ручным экранированием общих Public-переменных от одновременного обращения из двух потоков. Мне даже кажется это допустимым для элементарных задач (в моём случае в отдельном потоке всегда будет только один цикл на несколько строчек, сколь бы ни усложнялся основной проект). Знаю, что это наивная глупость, но ведь работает быстро и вроде стабильно...
Воплощено это так. Пока побочный поток пишет новый спрайт, главный поток считывает его прошлую версию. Для этого общий спрайт реализован в виде не просто переменной, а Public-массива с двумя индексами: -1 и 0, и индивидуального номера рабочего индекса. Пока читаем Sprite(nSprite), пишем в Sprite(Not nSprite), а по окончании записи переключаем рабочий номер: nSprite = Not nSprite, и вот уже читать в главном потоке будем обновлённый спрайт, пока побочный поток пишет в нерабочий спрайт. Вот так, меняя их местами, мы обеспечиваем изоляцию элементов массива от чтения из другого потока. При том что сам массив для обоих потоков общий, видимый отовсюду, и к тому же второй поток обращается напрямую к Webcam-контролу вызвавшей его формы из первого потока (!) и ко всем глобальным переменным, но поскольку явных обращений к Webcam-контролу из главного потока не происходит НИКОГДА и одновременного обращения к Public-переменным не происходит НИКОГДА (гарантированно), слётов и глюков пока не наблюдается. А если и слетит один раз из тысячи, это всё равно лучше, чем пихать обработку кадров с камеры в общий поток и ВСЕГДА наблюдать пьяную ступенчатую картинку.
Прочитав дискуссию Хакера с The Trick в теме
"Многопоточность - часть 4", я подумал: раз уж по-настоящему великие программисты не находят идеального подхода для StandardExe, то бог с ним, работает ведь - и ладно. Все API побочного потока объявлены локально в его модуле (интуиции кажется это более безопасным), встроенная функция Timer вставлена в поток лишь для пробы, она не нужна. Всё, что должен делать поток - снять карточку, обработать и выдать спрайт. И сколь бы ни усложнялся основной проект, отдельного потока это почти не коснётся, и свято блюсти его изоляцию не представляет труда. Вероятно, хитрости с подменой заголовка и т.д. в modMultiThreading действительно делают такой наивный подход возможным!
У вас нет доступа для просмотра вложений в этом сообщении.