C# WPF裁剪位图+;RenderTargetBitmap=EventHandler泄漏问题和冻结问题

C# WPF裁剪位图+;RenderTargetBitmap=EventHandler泄漏问题和冻结问题,c#,.net,wpf,eventhandler,rendertargetbitmap,C#,.net,Wpf,Eventhandler,Rendertargetbitmap,我想知道CroppedBitmap和RenderTargetBitmap周围是否存在.netEventHandler泄漏。这让我做了一场噩梦 我的WPF应用程序以60fps的速度运行始终运行的渲染调用。我注意到过了一段时间,呈现的内容变得越来越慢 经过大量调查,包括在VisualStudio中进行评测和使用ANTS内存分析器,我将范围缩小到使用裁剪位图 我有一些简单的问题演示代码,其中包括 RenderTargetBitmap srcBitmap = new RenderTargetBitmap

我想知道CroppedBitmap和RenderTargetBitmap周围是否存在.net
EventHandler
泄漏。这让我做了一场噩梦

我的WPF应用程序以60fps的速度运行始终运行的渲染调用。我注意到过了一段时间,呈现的内容变得越来越慢

经过大量调查,包括在VisualStudio中进行评测和使用ANTS内存分析器,我将范围缩小到使用裁剪位图

我有一些简单的
问题演示
代码,其中包括

RenderTargetBitmap srcBitmap = new RenderTargetBitmap((int)scaledWidth, (int)scaledHeight, 96, 96,     PixelFormats.Default);
RenderTargetBitmap destBitmap = new RenderTargetBitmap((int)scaledWidth, (int)scaledHeight, 96, 96,     PixelFormats.Default);

<code loop>
{...
    DrawingVisual DV = new DrawingVisual();
    DrawingContext DC = DV.RenderOpen();

    var srcRec = new Int32Rect(x,y,w,h);
    var srcCrop = new CroppedBitmap(srcBitmap, srcRec);

    var destRec = new Rect(.....);
    DC.DrawImage(srcCrop, destRec);

    DC.Close();
    destBitmap.Render(DV);

    DC = null;
    DV = null;
...}
RenderTargetBitmap srcBitmap=新的RenderTargetBitmap((int)scaledWidth,(int)scaledHeight,96,96,PixelFormats.Default);
RenderTargetBitmap destBitmap=新的RenderTargetBitmap((int)scaledWidth,(int)scaledHeight,96,96,PixelFormats.Default);

{...
DrawingVisual DV=新DrawingVisual();
DrawingContext DC=DV.renderropen();
var srcRec=new Int32Rect(x,y,w,h);
var srcCrop=新裁剪位图(srcBitmap,srcRec);
var destec=新的矩形(…);
DC.DrawImage(srcCrop,destRec);
DC.Close();
渲染(DV);
DC=null;
DV=null;
...}
使用SRCBAMPIMP调用CroppedBitmap后,SRCBAMPIMP将添加一个事件处理程序。具体来说,如果您将其分解为更精细的级别,则设置cropedBitmap.Source=srcBitmap将添加此事件处理程序

CroppedBitmap已下载完成、下载失败、下载进度事件。我猜是下载完成了

检查EventHandler的数量(使用srcBitmap/RenderTargetBitmap上的_downloadEvent属性),每次调用CroppedBitmap时,这确实会增加一个,而且永远不会减少。我只能得出结论,CroppedBitmap正在向RenderTargetBitmap添加一个事件处理程序,而RenderTargetBitmap永远不会被删除。运行一段时间后,RenderTargetBitmap上会出现x000的事件处理程序,我认为.net正在经历这一过程并导致速度下降

我一辈子都不知道该怎么办!图像被设置在一个简单的图像控件上,没有什么特别之处

我已经尝试过从发生这种情况时开始追踪到.net framework的深处,逐行逐行进行,但是当调试器开始命中优化的.net库时,我就迷失了方向,无法进一步挖掘

位图的显示很简单

Content.Source = srcBitmap;
....
<Image x:Name="Content" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderOptions.BitmapScalingMode="LowQuality" Stretch="None" IsHitTestVisible="False"></Image>
Content.Source=srcbamimp;
....
需要明确的是,作为一个示例,代码可以在没有渲染、没有绘制图像等的情况下运行,-只有新裁剪的位图。。。需要代码来显示这种行为。为了完整起见,上面包含了其他行。没什么区别

上面的示例是针对.NET Framework 4.7.2运行的,以确保最新版本存在此问题

我还尝试冻结裁剪的位图,以防万一会有不同。显然不是。事实上,调用srcCrop.Freeze会导致srcBitmap.isfreeze为true!呃。。。。。因此,裁剪位图似乎对其所裁剪的位图进行了更改

在上面找不到任何信息、帮助、文章等:(

请注意,这不是RenderTargetBitmap泄漏内存,您在支持论坛中看到了这一点,这是另外一回事。在不使用裁剪位图的情况下运行此代码就可以了。我在几个地方使用RenderTargetBitmap,都可以(我也已经解释了那篇文章中描述的内存使用率的增加,并且我已经调用了GC.Collect等。)我还重用了我的RenderTargetBitmaps,所以它们只创建一次(可能是为什么当对它们应用多个裁剪位图时,事件处理程序会堆积起来)

我曾尝试使用reflector拦截正在创建的事件处理程序,以便手动删除它们,但(尽管在互联网上有各种示例)无法找到它们隐藏的位置来执行此操作。必须在某个地方

有人知道我能做些什么来解决这个问题吗


提前感谢您的帮助…

您可以使用带有适当视口的ImageBrush,而不是使用裁剪位图:

var viewbox = new Rect(
    x * 96 / srcBitmap.DpiX,
    y * 96 / srcBitmap.DpiY,
    w * 96 / srcBitmap.DpiX,
    h * 96 / srcBitmap.DpiY);

var srcBrush = new ImageBrush
{
    ImageSource = srcBitmap,
    Viewbox = viewbox,
    ViewboxUnits = BrushMappingMode.Absolute,
};

// instead of DC.DrawImage(srcCrop, destRec);
DC.DrawRectangle(srcBrush, null, destRec);

先生,你是一个明星!我尝试了这个,并取得了成功。请注意,性能基准测试,我没有看到任何不同,我是如何做的。谢谢你。我仍然非常感兴趣,但为什么裁剪位图会导致东西塞满…不客气。你可能想看看源代码参考.NET中的源代码