Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to freeze freezable objects that cannot be frozen

In my scenario I want to freeze a non changing BitmapCacheBrush before I want to render it in a background task. Unfortunately I receive the error "This Freezable cannot be frozen". Is there any workaround or hacky way freeze also not freezable objects? Maybe it is possible to set the right properties via reflection to reach this goal? Thank you guys in advance.

Edit: (My sample code as requested)

 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;
    }

}
like image 444
Andreas Avatar asked Apr 13 '16 13:04

Andreas


People also ask

What material Cannot be frozen?

Vitrification. Certain materials, such as glass and glycerol, may harden without crystallizing; these are called amorphous solids. Amorphous materials, as well as some polymers, do not have a freezing point, as there is no abrupt phase change at any specific temperature.

How do you freeze objects?

Object.freeze() Method freeze() which is used to freeze an object. Freezing an object does not allow new properties to be added to an object and prevents from removing or altering the existing properties. Object. freeze() preserves the enumerability, configurability, writability and the prototype of the object.

Which of the following have two states of freezable object?

A Freezable is a special type of object that has two states: unfrozen and frozen. When unfrozen, a Freezable appears to behave like any other object.

What is a freeze method?

freezing, in food processing, method of preserving food by lowering the temperature to inhibit microorganism growth. The method has been used for centuries in cold regions, and a patent was issued in Britain as early as 1842 for freezing food by immersion in an ice and salt brine.


1 Answers

First, you need to figure out WHY you can't freeze it. Get into the registry and set ManagedTracing to 1 (if you have to make it, it's a REG_DWORD type). I suggest you add it to your Favorites in regedit so you can quickly get to it when you need to turn it on/off.

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Tracing\WPF\ManagedTracing

When you try to freeze the BitmapCacheBrush or check the bool property BitmapCacheBrush.CanFreeze, you will get a warning in the Output tab in visual studio telling you what the problem is.

I made a test case based off code from https://blogs.msdn.microsoft.com/llobo/2009/11/10/new-wpf-features-cached-composition/

And the warning it gave me was:

System.Windows.Freezable Warning: 2 : CanFreeze is returning false because a DependencyProperty on the Freezable has a value that is a DispatcherObject with thread affinity; Freezable='System.Windows.Media.BitmapCacheBrush'; Freezable.HashCode='29320365'; Freezable.Type='System.Windows.Media.BitmapCacheBrush'; DP='Target'; DpOwnerType='System.Windows.Media.BitmapCacheBrush'; Value='System.Windows.Controls.Image'; Value.HashCode='11233554'; Value.Type='System.Windows.Controls.Image'

BitmapCacheBrush.Target is of type Visual and all Visuals are derived from DependencyObject which is derived from DispatcherObject. And according to https://msdn.microsoft.com/en-us/library/ms750441(v=vs.100).aspx#System_Threading_DispatcherObject

By deriving from DispatcherObject, you create a CLR object that has STA behavior, and will be given a pointer to a dispatcher at creation time.

So, all Visuals are STA which means you can't freeze BitmapCacheBrush unless you set it's Target to null.

like image 115
J.H. Avatar answered Nov 11 '22 05:11

J.H.