WPF: Как я могу предотвратить разрыв с WriteableBitmap?
Я использую WriteableBitmap
для отображения изображений я обрабатываю себя со скоростью около 20 кадров в секунду.
Этот вопрос ( WPF: более эффективный способ отображения быстро меняющихся изображений?)
и этот вопрос ( как отображать быстро обновляемые изображения без большого выделения памяти?)
указать, что лучший способ сделать это с помощью WriteableBitmap
,
Документация для WriteableBitmap
указывает на то, что вызов WritePixels()
в потоке пользовательского интерфейса заставит поток рендеринга перерисовать изображение:
Документация MSDN:
Поток пользовательского интерфейса записывает содержимое в задний буфер. Поток рендеринга читает содержимое из переднего буфера и копирует его в видеопамять. Изменения в заднем буфере отслеживаются с измененными прямоугольными областями.
Когда обновления отправляются в поток рендеринга, поток рендеринга копирует измененные прямоугольники из заднего буфера в передний буфер. Система рендеринга контролирует этот обмен, чтобы избежать тупиков и артефактов перерисовки, таких как "разрыв".
Я обрабатываю свои изображения в фоновом потоке, а затем использую Dispatcher.BeginInvoke()
звонить WritePixels()
, чтобы убедиться, что WritePixels()
вызывается в потоке пользовательского интерфейса.
Я обнаружил, что разрыв все еще происходит с WriteableBitmap
и в приложении, над которым я работаю, выглядит ужасно (это приложение для медицинской визуализации). Что я могу сделать?
3 ответа
Было много работы, вложенной в WriteableBitmap, чтобы избежать разрывов, но в некоторых конфигурациях системы это неизбежно. Это в основном происходит в Windows XP или Vista с отключенным Aero (DWM).
Когда вы вызываете WritePixels(), возможно, вы перезаписываете свое растровое изображение. Использование Dispatcher.Invoke() вместо BeginInvoke() может помочь.
Я знаю, что это старый поток, но у нас была точно такая же проблема, и в нашем случае она была вызвана вызовом нашего метода отображения обновлений с использованием Dispatcher.BeginInvoke - в тот момент, когда мы изменили на Dispatcher.Invoke, он сразу же очистился.