在我的场景中,我想先冻结不变的 BitmapCacheBrush,然后再在后台任务中渲染它。不幸的是,我收到错误“此 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;
}
}
首先,您需要弄清楚为什么不能冻结它。进入注册表并将 ManagedTracing 设置为 1(如果一定要设置,则为 REG_DWORD 类型)。我建议您将其添加到注册表中的收藏夹中,以便在需要打开/关闭它时可以快速找到它。
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Tracing\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;
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'
BitmapCacheBrush.Target 属于 Visual 类型,所有 Visual 都派生自 DependencyObject,而 DependencyObject 又派生自 DispatcherObject。并根据https://msdn.microsoft.com/en-us/library/ms750441(v=vs.100).aspx#System_Threading_DispatcherObject
通过从 DispatcherObject 派生,您可以创建一个 CLR 对象,该对象具有
STA 行为,并将在创建时获得指向调度程序的指针
时间。
因此,所有 Visuals 都是 STA,这意味着您无法冻结 BitmapCacheBrush,除非您将其 Target 设置为 null。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)