2016-04-13 6 views
5

В моем сценарии я хочу заморозить неизменяемый BitmapCacheBrush, прежде чем я хочу отобразить его в фоновом задании. К сожалению, я получаю сообщение об ошибке «Этот Freezable не может быть заморожен». Есть ли обходной или хакерский способ замораживания и не зависание объектов? Возможно, возможно установить нужные свойства через отражение для достижения этой цели? Спасибо, ребята, заранее.Как заморозить замороженные объекты, которые не могут быть заморожены

Edit: (Мой пример кода по запросу)

public static class ext 
{ 
    public static async Task<BitmapSource> RenderAsync(this Visual visual) 
    { 
     var bounds = VisualTreeHelper.GetDescendantBounds(visual); 

     var bitmapCacheBrush = new BitmapCacheBrush(visual); 
     bitmapCacheBrush.BitmapCache = new BitmapCache(); 

     // We need to disconnect the visual here to make the freezable freezable :). Of course this will make our rendering blank 
     //bitmapCacheBrush.Target = null; 

     bitmapCacheBrush.Freeze(); 

     var bitmapSource = await Task.Run(() => 
     { 
      var renderBitmap = new RenderTargetBitmap((int)bounds.Width, 
                 (int)bounds.Height, 96, 96, PixelFormats.Pbgra32); 

      var dVisual = new DrawingVisual(); 
      using (DrawingContext context = dVisual.RenderOpen()) 
      { 

       context.DrawRectangle(bitmapCacheBrush, 
             null, 
             new Rect(new Point(), new Size(bounds.Width, bounds.Height))); 
      } 

      renderBitmap.Render(dVisual); 
      renderBitmap.Freeze(); 
      return renderBitmap; 
     }); 

     return bitmapSource; 
    } 

} 
+23

Я думаю, что это мое любимое название вопроса до сих пор. –

+0

Я ничего не знаю о C# и друзьях, но заголовок такой приятной загадки! он бьет по дереву. И, следуя духу, ответ: «Вы не можете заморозить замороженные объекты, которые не могут быть заморожены!» – SergeyA

+2

Спросите Эльсу, чтобы помочь :) – Guy

ответ

4

Во-первых, вы должны выяснить, почему вы не можете заморозить его. Войдите в реестр и установите ManagedTracing в 1 (если вам нужно это сделать, это тип REG_DWORD). Я предлагаю вам добавить его в Избранное в regedit, чтобы вы могли быстро добраться до него, когда вам нужно включить/выключить его.

HKEY_CURRENT_USER \ SOFTWARE \ Microsoft \ Tracing \ WPF \ ManagedTracing

При попытке заморозить BitmapCacheBrush или проверить BOOL свойство BitmapCacheBrush.CanFreeze, вы получите предупреждение во вкладке Output в визуальный студия говорит вам, в чем проблема.

Я сделал тест, основанный от кода из https://blogs.msdn.microsoft.com/llobo/2009/11/10/new-wpf-features-cached-composition/

И предупреждение это дало мне было:

System.Windows.Freezable Предупреждение: 2: CanFreeze возвращается ложь, потому что DependencyProperty на Freezable имеет значение, равное DispatcherObject с привязкой к потоку; Freezable = 'System.Windows.Media.BitmapCacheBrush'; Freezable.HashCode = '29320365'; Freezable.Type = 'System.Windows.Media.BitmapCacheBrush'; DP = 'Target'; DpOwnerType = 'System.Windows.Media.BitmapCacheBrush'; Значение = 'System.Windows.Controls.Image'; Value.HashCode = '11233554'; Value.Type = «» System.Windows.Controls.Image

BitmapCacheBrush.Target имеет тип Визуальный и все визуалы являются производными от DependencyObject, который получен из DispatcherObject. И в соответствии с https://msdn.microsoft.com/en-us/library/ms750441(v=vs.100).aspx#System_Threading_DispatcherObject

наследованием от DispatcherObject, вы создаете объект CLR, который имеет поведение STA, и будет дан указатель диспетчеру на создание времени.

Итак, все визуальные объекты - это STA, что означает, что вы не можете заморозить BitmapCacheBrush, если вы не задали для него Target значение null.

Смежные вопросы