如何冻结无法冻结的可冻结对象 [英] How to freeze freezable objects that cannot be frozen

查看:111
本文介绍了如何冻结无法冻结的可冻结对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的方案中,我想冻结一个不变的BitmapCacheBrush,然后再将其渲染到后台任务中.不幸的是,我收到错误消息此Freezable无法冻结".是否有任何解决方法或黑客方式冻结也不冻结的对象?也许可以通过反射设置正确的属性来实现此目标?谢谢大家.

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.

(按要求提供我的示例代码)

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

}

推荐答案

首先,您需要弄清楚为什么不能冻结它.进入注册表并将ManagedTracing设置为1(如果必须创建,则为REG_DWORD类型).建议您将其添加到regedit的收藏夹"中,以便在需要打开/关闭它时可以快速获取它.

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

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Tracing\WPF\ManagedTracing

当您尝试冻结BitmapCacheBrush或检查bool属性BitmapCacheBrush.CanFreeze时,您将在Visual Studio的输出"选项卡中收到一条警告,告诉您问题出在哪里.

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.

我根据 https://blogs.msdn.microsoft.com/llobo/2009/11/10/new-wpf-features-cached-composition/

它给我的警告是:

System.Windows.Freezable警告:2:CanFreeze返回false是因为Freezable上的DependencyProperty的值为具有线程关联性的DispatcherObject;Freezable ='System.Windows.Media.BitmapCacheBrush';Freezable.HashCode ='29320365';Freezable.Type ='System.Windows.Media.BitmapCacheBrush';DP ='目标';DpOwnerType ='System.Windows.Media.BitmapCacheBrush';值='System.Windows.Controls.Image';Value.HashCode ='11233554';Value.Type ='System.Windows.Controls.Image'

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的类型为Visual,并且所有Visuals均从DependencyObject派生,而DependencyObject派生自DispatcherObject.并根据 https://msdn.microsoft.com/zh-CN/library/ms750441(v = vs.100).aspx#System_Threading_DispatcherObject

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

通过从DispatcherObject派生,您可以创建一个具有以下内容的CLR对象:STA行为,在创建时将被赋予指向调度程序的指针时间.

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.

因此,所有视觉效果都是STA,这意味着除非将Target的Target设置为null,否则您将无法冻结BitmapCacheBrush.

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

这篇关于如何冻结无法冻结的可冻结对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆