'in a class that gets a ref to acad, how to set to nothing and release reference
'Tony said don't need to override finalize but i don't see where else to clear acad vars in a dotnet class
'since they don't have a built in Terminate like vb6 does.
'so is this right or not?
Protected Overrides Sub Finalize()
m_acadDoc = Nothing
m_AcadApp = Nothing
Marshal.ReleaseComObject(m_AcadApp)
Marshal.ReleaseComObject(m_acadDoc)
MyBase.Finalize()
End Sub
End Clas
thanks
mark
You implement IDisposable on your class, and put the
code you show in your Finalize() override in the Dispose()
method, and you call Dispose() when your application
shuts down.
I suggest you read up on Finalize() and why you can't
use it the way you want. Finalize() can be called at any
time, including long after the objects you are trying to
acess from your Finalize() have themselves already
been Finalized().
You can't assume that any managed object is still
'alive' when Finalize() is called. What if the objects
you're trying to access from your Finalize() have
already had their Finalize() called, which destroys
them and makes them unusable?
Thanks Tony,
I'm obviously struggling with this new learning curve. Trying to wrap my head around implementing disposable
my app structure(right or wrong ) is
commands.vb <--defines acad commands
mcsdxf.vb <-- "main" class with command implementation
mcsutil.vb <-- 'utility' class that gets acad (and other common funcs)
in command.vb
Public Class AcadCommands
Private inst As New MCSdxf
<CommandMethod("Cnc", CommandFlags.Session)> _
Public Sub CncPartList()
If inst Is Nothing Then inst = New MCSdxf
If inst.Init() Then
'MsgBox("Init passed")
Else
'MsgBox("Init failed")
End If
inst.CNC_FormPartList()
'is this where i'd call inst.Dispose if i make mcsdxf implement iDisposable???
End Sub
in MCSdxf.vb
Private m_acad As AcadApplication
Function Init() As Boolean
m_Util = New MCSUtil(True)
m_Util.Init2(True)
If m_acad Is Nothing Then
m_acad = m_Util.ACAD
....
End Function
Sub CNC_FormPartList()
...code...
'code is now done, is this where i'd call m_Util.Dispose if i make mcsutil implement iDisposable???
End Sub
in MCSutil.vb
Function Init2(ByVal bDebug As Boolean) As Boolean
m_Debug = bDebug
Try
m_AcadApp = DirectCast(Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication, AcadApplication)
m_acadDoc = m_AcadApp.ActiveDocument
Return True
Catch ex As Exception
Return False
End Try
....
so my question is...
does mcsdxf implement iDisposable or does mcsuitl implement it or do both implement it?
then when mcxdxf.App1 is done with it's routine, it calls mcsutil.Dispose?
and when command.vb commandwhatever is done it calls mcsdxf.dispose?
question2
in mcsdxf I have an m_acad variable which is set to mutil.Acad property
maybe i should not create that variable and just use the utility class .acad object directly?
i hope those questions are clear
thanks for all your help
mark
for now i tried this (while i figure out the implements iDisp method)
i put a pub method on the util obj
Public Sub ReleaseAcad()
Marshal.ReleaseComObject(m_acadDoc)
Marshal.ReleaseComObject(m_AcadApp)
m_acadDoc = Nothing
m_AcadApp = Nothing
End Sub
so when app finishes , it calls m_Util.ReleaseAcad
likewise i put a pub method on mcsdxf.vb object
Public Sub ReleaseAcad()
Marshal.ReleaseComObject(m_acadDoc)
Marshal.ReleaseComObject(m_acad)
m_acadDoc = Nothing
m_acad = Nothing
m_Util.ReleaseAcad()
m_Util.OpenDebugLog()
m_Util = Nothing
End Sub
so when the command method ends it calls mcsdxf.ReleaseAcad
<CommandMethod("CncArc", CommandFlags.Session)> _
Public Sub CncArcList()
If inst Is Nothing Then inst = New MCSdxf
inst.Init()
inst.CNC_ArcFormPartList()
inst.ReleaseAcad()
End Sub
obviously the defect is i have to remember to call those methods.
presumably when i get the implementation of Dispose working that could become automatic
is that close?
thanks
mark
fwiw,
i'm sure it's not the right way to do it but acad does seem to be closing properly now
obviously in dotnet the variables aren't being destroyed when they go out of scope like they would have in vb6
or so it seems
If your code is in a NETLOADed dll, how are you getting the
AcadApplication object?
I ask this, becaused none of that should be needed when
you're using COM from a NETLOADed dll.
Private Function GetAutoCADInstance() As AcadApplication
Try
m_AcadApp = DirectCast(Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication, AcadApplication)
Catch ex As Exception
Me.Logentry("Failed to get acad application " + ex.Message)
m_AcadApp = Nothing
End Try
Return m_AcadApp
End Function
that's in m_util class
i keep getting fatal error now
None of the things you're doing in your Finalize() need to be
done when your code is running in a NETLOADed dll.
Unless you are using AxDbDocuments and not releasing
them, I can't think of any reason why AutoCAD would
not shut down.
As far as the fatal error, that's being caused by your
code. If you're overriding Finalize() that might explain it.
per your info I have removed all finalize subs (commented out)
but the ide keeps putting them back automatically
'i commented this out
'Protected Overrides Sub Finalize()
' MyBase.Finalize()
'End Sub
'then it appeared again automatically?!?
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
I made the two classes implement iDisposable
in Dispose i called the ReleaseAcad sub
the ide automatically added the implementation apparently
i just added in my call to ReleaseAcad
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
ReleaseAcad()
' TODO: free other state (managed objects).
End If
' TODO: free your own state (unmanaged objects).
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
for unknown reson today is not crashing, and acad is closing properly
does my implementation of dispose and ReleaseAcad above appear correct to you?
seems to work today, i'll see what tomorrow brings
🙂
thanks for your guidance
mark
Maybe you didn't see my last reply.
You don't need to release any AutoCAD COM objects when your code
is running in a NETLOADed DLL, so you don't have to bother with the
IDisposable business.
am i supposed to call .Dispose on my objects or does the system do that when they go out of scope?
thanks
mark
You apparently aren't reading my posts.
I mentioned two times that you don't need to implement IDisposable
on objects in a NETLOADed DLL to release AutoCAD COM objects.
To answer your question, no the system doesn't call Dispose(),
you must call it.