如何冻结无法冻结的freezable对象

时间:2016-04-13 13:10:11

标签: c# wpf multithreading rendertargetbitmap freezable

在我的场景中,我想在我想在后台任务中渲染它之前冻结一个不变的BitmapCacheBrush。不幸的是我收到了错误"这个Freezable无法冻结"。 是否有任何解决方法或hacky方式冻结也不是freezable对象? 也许可以通过反射设置正确的属性来达到这个目标?提前谢谢你们。

编辑:(我提供的示例代码)

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

}

1 个答案:

答案 0 :(得分:5)

首先,你需要弄清楚为什么你不能冻结它。进入注册表并将ManagedTracing设置为1(如果必须这样做,则为REG_DWORD类型)。我建议你在regedit中将它添加到你的收藏夹中,这样你就可以在需要打开/关闭它时快速找到它。

  

HKEY_CURRENT_USER \ SOFTWARE \微软\跟踪\ WPF \ ManagedTracing

当您尝试冻结BitmapCacheBrush或检查bool属性BitmapCacheBrush.CanFreeze时,您将在visual studio的“输出”选项卡中收到警告,告诉您问题所在。

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

的代码制作了一个测试用例

它给我的警告是:

  

System.Windows.Freezable警告:2:CanFreeze返回false,因为Freezable上的DependencyProperty具有的值是   具有线程亲和性的DispatcherObject;   可冷冻= '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'

BitmapCacheBrush.Target是Visual类型,所有Visuals都派生自DependencyObject,派生自DispatcherObject。根据{{​​3}}

  

通过派生DispatcherObject,您可以创建一个具有的CLR对象   STA行为,并将在创建时给出指向调度程序的指针   时间。

因此,所有Visual都是STA,这意味着你不能冻结BitmapCacheBrush,除非你将它的Target设置为null。