我有一个基于SharpDX的C#应用程序。有一种情况允许用户编辑线性渐变,但由于我没有找到修改ID2D1GradientStopCollection
(又名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:创建+ 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的, System.Collections.Specialized.NotifyCollectionChangedEventArgs)
正如你所看到的,我确保处理画笔和渐变停止集合(当删除画笔时它似乎仍然存在)。但是,我的应用程序的本机内存使用量继续稳步增长,CLR垃圾收集器无法解释。
答案 0 :(得分:0)
错误发生在我创建渐变停止集合中: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();
}