繁体   English   中英

WPF CroppedBitmap + RenderTargetBitmap = EventHandler泄漏问题和冻结问题

[英]WPF CroppedBitmap + RenderTargetBitmap = EventHandler leak problem and Freeze problem too

我想知道CroppedBitmap和RenderTargetBitmap周围是否存在.net EventHandler泄漏。 真是一场噩梦!

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

经过大量的研究,包括在Visual Studio中进行分析以及使用ANTS内存分析器,我将其范围缩小到使用CroppedBitmap。

我已经demonstration of problem代码进行了一些简单的demonstration of problem ,其中包括...

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

使用srcBitmap调用CroppedBitmap之后,srcBitmap会添加一个事件处理程序。 具体来说,如果将其分解为更精细的级别,则设置CroppedBitmap.Source = srcBitmap将添加此事件处理程序。

CroppedBitmap具有DownloadCompleted,DownloadFailed,DownloadProgress事件。 我会猜测是DownloadCompleted。

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

我无法终生解决该问题! 该图像是在一个简单的Image控件上设置的,没什么花哨的。

我试图逐一逐一地追溯到.net框架的深度,但是当调试器开始访问优化的.net库时迷路了,无法进一步挖掘。

位图的表示很简单...

Content.Source = srcBitmap;
....
<Image x:Name="Content" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderOptions.BitmapScalingMode="LowQuality" Stretch="None" IsHitTestVisible="False"></Image>

为了清楚起见,例如,该代码可以在不渲染,不绘制图像等情况下运行,仅需要新的CroppedBitmap ...代码即可显示此行为。 为了完整起见,其他行也包含在上面。 没有区别。

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

我还尝试了冻结CroppedBitmap,以防万一。 显然不是。 实际上,调用srcCrop.Freeze导致srcBitmap.isFrozen为true! erm .....,看来CroppedBitmap对要裁剪的位图进行了更改?

找不到上述的任何信息,帮助,文章等:(

请注意,这不是您在支持论坛中提到的RenderTargetBitmap泄漏内存,这是另外一回事。 在不使用CroppedBitmap的情况下运行此代码,这很好。 我在几个地方都使用了RenderTargetBitmaps,一切都很好(我也已经按照该文章所述考虑了增加内存使用的问题,并且我已经在调用GC.Collect等)。 我还重用了RenderTargetBitmaps,因此它们仅创建一次。 (可能是为什么将多个CroppedBitmap应用于事件处理程序时堆积事件处理程序的原因)。

我尝试使用反射器来捕获正在创建的事件处理程序,以便可以手动将其删除,但是(尽管在互联网上有各种示例)无论在什么地方藏起来都无法掌握它们。 必须在某个地方!

任何人有什么想法我可以做些什么来解决这个问题?

感谢您的提前帮助...

除了使用CroppedBitmap,还可以将ImageBrush与适当的Viewbox结合使用:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM