And*_*eas 5 c# wpf multithreading freezable rendertargetbitmap
在我的场景中,我想在我想在后台任务中渲染它之前冻结一个不变的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;
}
}
Run Code Online (Sandbox Code Playgroud)
首先,你需要弄清楚为什么你不能冻结它.进入注册表并将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.并根据https://msdn.microsoft.com/en-us/library/ms750441(v=vs.100).aspx#System_Threading_DispatcherObject
通过从DispatcherObject派生,您可以创建具有STA行为的CLR对象,并在创建时为其指定调度程序.
因此,所有Visual都是STA,这意味着你不能冻结BitmapCacheBrush,除非你将它的Target设置为null.