WPF BitmapFrame и несколько потоков

У меня есть файл PNG, хранящийся в моем облаке в хранилище больших двоичных объектов, я хочу загрузить его и отобразить на экране в WPF.

Я знаю о Диспетчере и Замораживании, но ничего не работает. Я продолжаю получать сообщение об ошибке «другой поток владеет им».

Вот что у меня есть:

var decoder = GetDecoder("http://address/image.png");

Dispatcher.Invoke(DispatcherPriority.Send, new Action<BitmapFrame>(SetImage), decoder.Frames[0]);

public void SetImage(BitmapFrame source)
{
    var bitmapFrame = BitmapFrame.Create(source);  //ERROR HERE!!!!!!!!
    LazyImage.Source = bitmapFrame;
}

private BitmapDecoder GetDecoder(object uri)
{
    var extension = System.IO.Path.GetExtension((string)uri);
    BitmapDecoder decoder = null;
    if (extension.ToLower() == ".png")
        decoder = BitmapDecoder.Create(new Uri((string)uri, UriKind.Absolute), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
    return decoder;
}

Если я попытаюсь заморозить Frame[0], я получу исключение, говорящее, что этот Frame не может быть заморожен. Кроме того, декодер, возвращаемый BitmapDecoder.Create, является не PngBitmapDecoder, а LateBoundBitmapDecoder, который я действительно не знаю, как эффективно использовать.


person Mark    schedule 09.02.2011    source источник


Ответы (3)


Возможно, вам нужно не только создать Bitmapframe в диспетчере, но и BitmapDecoder? Вы пытались вызвать GetDecoder в диспетчере?

person Lugoues    schedule 09.02.2011
comment
возможно, я думаю, что создание декодера является синхронной операцией, что означает, что я хотел бы избежать этого в потоке пользовательского интерфейса. Имейте в виду, файлы на моем локальном ПК (не URL-адреса http) работают нормально, потому что декодер PngBitmapDecoder - person Mark; 09.02.2011
comment
Ну... возможно, вы можете вызвать BitmapFrame.Create() в потоке и попытаться заморозить возвращаемый им кадр? - person Lugoues; 09.02.2011
comment
Если я замораживаю кадр, возвращаемый LateBoundBitmapDecoder, я получаю исключение, но если я использую локальный URL-адрес (и, следовательно, PngBitmapDecoder), я могу заморозить его, и он отлично работает. - person Mark; 09.02.2011
comment
Поискал и нашел это: social.msdn.microsoft.com/Forums/en-US/wpf/thread/ Прокрутите вниз до ответа Дуэйна Нида, у него есть источник для демонстрации, которая выполняет асинхронную загрузку, что должно обойти проблему, с которой вы столкнулись. имея. - person Lugoues; 09.02.2011
comment
Хорошо, похоже, мои проблемы были больше связаны с тем фактом, что я создал BitmapImage в потоке BG и попытался передать его в поток пользовательского интерфейса, но по какой-то причине я не мог клонировать или заморозить его, поэтому я просто передал byte[] в поток пользовательского интерфейса и создание изображения с использованием этого... Я дам вам баллы, потому что вы были единственным, кто ответил - person Mark; 14.02.2011

Вкратце: попробуйте обернуть результат в WriteableBitmap.

Длинная история с кодом.

person bohdan_trotsenko    schedule 27.01.2012
comment
В моем случае это было единственное решение, которое сработало. Мне нужно было передать BitmapFrame в TransformedBitmap. Не имел контроля над тем, в каком потоке был создан BitmapFrame, поскольку он предоставляется библиотекой (и свойство Dispatcher BitmapFrame имеет значение null). Даже запрос свойства CanFreeze вызывал исключение. У меня было два варианта: капитальный ремонт исходного кода моего и других, или использовать WriteableBitmap. Угадайте, что я выбрал... - person ; 21.11.2013

Это проблема и сегодня! Обертка данных в WriteableBitmap, как предложил Богдан, будет работать, но этот тип имеет передний и задний буфер, что удваивает его объем памяти. CachedBitmap - лучший выбор.

new CachedBitmap(bitmapSource, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

Используйте BitmapCacheOption.OnLoad, если вам не нравятся сюрпризы, и не забудьте также заморозить получившийся объект.

person Artfunkel    schedule 08.05.2020