神秘的Direct2D内存泄漏与渐变
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神秘的Direct2D内存泄漏与渐变相关的知识,希望对你有一定的参考价值。
我有一个基于SharpDX的C#应用程序。有一种情况允许用户编辑线性渐变,但由于我没有找到修改ID2D1GradientStopCollection
(aka SharpDX.Direct2D1.GradientStopCollection
)的方法,我只是处理并重新创建用户调整偏移量的每一帧的渐变。渐变停止。
但是,我注意到如果我调整渐变停止足够的次数(即,在每秒重新创建60次线性渐变的同时将其拖动10秒钟),那么我注意到我的应用程序的内存使用量没有限制。我确定我在梯度上调用Dispose
:
private void RecreateBrush()
{
var old = (SharpDX.Direct2D1.LinearGradientBrush)NativeBrush;
NativeBrushLock.EnterWriteLock();
NativeBrush = new SharpDX.Direct2D1.LinearGradientBrush(
Target,
new LinearGradientBrushProperties
{
StartPoint = new RawVector2(StartX, StartY),
EndPoint = new RawVector2(EndX, EndY)
},
ConvertStops());
old.GradientStopCollection.Dispose();
old.Dispose();
NativeBrushLock.ExitWriteLock();
}
但我的记忆力仍在继续增加。使用dotMemory对应用程序进行分析后发现,内存增加都是非托管内存,因此我开始深入挖掘,并使用DebugDiag 2.0来分析我的应用程序。 DebugDiag的分析指出d3d11!NOutermost::CDevice::CreateLayeredChild+15f
是分配所有内存的罪魁祸首,其“泄漏概率”为100%。
这是什么意思,我如何摆脱内存泄漏?据我所知,我正在处理我正在创造的所有资源(ID2D1LinearGradient
和ID2D1GradientStopCollection
)。
这是我从WinDbg收集的堆栈跟踪:
d3d11!NOutermost :: CDevice :: CreateLayeredChild d3d11!CDevice :: CreateTexture2D_Worker + 0x47e d3d11!CDevice :: CreateTexture2D + 0xbf d2d1!CD3DDeviceCommon :: CreateTexture + 0x4c d2d1!CD3DSurface :: Create + 0xe1 d2d1!D2DGradientStopCollection :: EnsureRealizedForBrushType + 0x239 d2d1 !D2DGradientBrush :: SetGradientStopCollectionInternal + 0x85 D2D1!D2DLinearGradientBrush:创建+ 0x8c D2D1!的DrawingContext :: CreateLinearGradientBrush + 0xce D2D1!D2DDeviceContextBase :: CreateLinearGradientBrush + 0xe7 [托管到本机过渡] SharpDX.Direct2D1.RenderTarget.CreateLinearGradientBrush(SharpDX.Direct2D1.LinearGradientBrushProperties ,System.Nullable`1,SharpDX.Direct2D1.GradientStopCollection,SharpDX.Direct2D1.LinearGradientBrush)SharpDX.Direct2D1.LinearGradientBrush..ctor(SharpDX.Direct2D1.RenderTarget,SharpDX.Direct2D1.LinearGradientBrushProperties,SharpDX.Direct2D1.GradientStopCollection)MyApp.Direct2D。 LinearGradientBrush.RecreateBrush()MyApp.Direct2D.LinearGradientBrush.OnStopsChanged(System.Object,Syst em.Collections.Specialized.NotifyCollectionChangedEventArgs)
正如你所看到的,我确保处理画笔和渐变停止集合(当删除画笔时它似乎仍然存在)。但是,我的应用程序的本机内存使用量继续稳定增长,CLR垃圾收集器无法解释。
错误发生在我创建渐变停止集合中:ConvertStops()产生一个SharpDX.Direct2D1.GradientStopCollection
。但是,在调用LinearGradientBrush
的构造函数之后,我需要确保处理该渐变停止集合,因为虽然返回的LinearGradientBrush
具有表示指向同一值的指针的属性GradientStopCollection
,但它不是同一个.NET实例。因此,通过从LinearGradientBrush.GradientStopCollection
检索它来处置它不会将引用计数减少到0,并且数据继续存在。
修改后的RecreateBrush
方法如下所示:
private void RecreateBrush()
{
var old = (SharpDX.Direct2D1.LinearGradientBrush) NativeBrush;
NativeBrushLock.EnterWriteLock();
using (var nativeStops = ConvertStops())
NativeBrush = new SharpDX.Direct2D1.LinearGradientBrush(
Target,
new LinearGradientBrushProperties
{
StartPoint = new RawVector2(StartX, StartY),
EndPoint = new RawVector2(EndX, EndY)
},
nativeStops);
old.Dispose();
NativeBrushLock.ExitWriteLock();
}
以上是关于神秘的Direct2D内存泄漏与渐变的主要内容,如果未能解决你的问题,请参考以下文章