我准备了一个可运行的插件,可用于重现我所描述的内存泄漏。附加的解决方案是在VS 2010中编写的,并使用AutoCAD 2014和2016进行了测试(我只在2014年进行了调试)。它应该在2013年至2016年间的任何版本中运行。我在bin\Debug中包含了一个工作dll。
我已经包含了我的插件使用的动态块的一小部分,以便重现问题。插件定义了一个命令(RunAutomatedMemoryLeakTest)。插件为每个动态块创建10个实例,然后将每个可用的属性值设置3次,其中属性类型代码为5。内存量与每个属性设置的块数/次数成正比。通过更改for循环可以轻松调整内存消耗量。
插入块和读取块属性似乎都不会导致内存消耗。内存消耗是由调用DynamicBlockHelper.SetParameter.引起的
这是命令的代码(对不起,我的雇主需要vb.net):
-
- _
- Public Shared Sub AutoMemoryLeakTestCommand()
- If Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument IsNot Nothing Then
- Dim blockObjectIDs As New List(Of ObjectId)
- Dim directoryPath As String = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
- For x As Integer = 1 To 10
- For Each filePath In Directory.GetFiles(directoryPath)
- If Path.GetExtension(filePath).Equals(".dwg", StringComparison.OrdinalIgnoreCase) Then
- DynamicBlockHelper.AddDynBlockToDrawingFromFile(filePath, Path.GetFileNameWithoutExtension(filePath))
- blockObjectIDs.Add(DynamicBlockHelper.InsertBlock(HostApplicationServices.WorkingDatabase, BlockTableRecord.ModelSpace, New Point3d(0, 0, 0), Path.GetFileNameWithoutExtension(filePath), 1, 1, 1, "NONE"))
- End If
- Next
- Next
- For x As Integer = 1 To 3
- For Each objID In blockObjectIDs
- Dim blockProperties = DynamicBlockHelper.GetBlockProperties(objID)
- For Each blockProp In blockProperties
- Dim propertyAttribs() As String = blockProp.Key.Split("~")
- Dim propertyName As String = propertyAttribs(0)
- Dim propertyType As String = propertyAttribs(2)
- If propertyType = 5 AndAlso blockProp.Value.Count > 1 Then
- For Each propValue As String In blockProp.Value
- DynamicBlockHelper.SetParameter(objID, propertyName, propValue)
- Next
- End If
- Next
- Next
- Next
- End If
- End Sub
这是SetParameter方法的代码:
-
- Public Shared Function SetParameter(ByVal BlockID As ObjectId, ByVal ParameterName As String, ByVal Value As String) As Boolean
- Dim doc As Document = ApplicationServices.Application.DocumentManager.GetDocument(BlockID.Database)
- Using lock As DocumentLock = doc.LockDocument()
- Using myTrans As Transaction = BlockID.Database.TransactionManager.StartOpenCloseTransaction()
- Try
- Using myBRef As BlockReference = myTrans.GetObject(BlockID, OpenMode.ForWrite)
- For Each myDynamProp As DynamicBlockReferenceProperty In _
- myBRef.DynamicBlockReferencePropertyCollection
- If myDynamProp.PropertyName.Equals( _
- ParameterName, StringComparison.OrdinalIgnoreCase) = True Then
- myDynamProp.Value = Value
- myTrans.Commit()
- Return True
- End If
- Next
- End Using
- Catch ex As System.Exception
- myTrans.Abort()
- Try
- EventLog.WriteEntry("MemLeakTest", ex.GetType().Name + ": " + ex.Message + Environment.NewLine + ex.StackTrace, EventLogEntryType.Error)
- Catch eex As System.Exception
- End Try
- End Try
- Return False
- End Using
- End Using
- End Function
谢谢,
凯文 |