.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Is this the right way to Marshal.ReleaseComObject(m_AcadApp)

12 REPLIES 12
Reply
Message 1 of 13
Anonymous
865 Views, 12 Replies

Is this the right way to Marshal.ReleaseComObject(m_AcadApp)

'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

12 REPLIES 12
Message 2 of 13
Anonymous
in reply to: Anonymous

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?

Message 3 of 13
Anonymous
in reply to: Anonymous

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

 

Message 4 of 13
Anonymous
in reply to: Anonymous

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

Message 5 of 13
Anonymous
in reply to: Anonymous

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

Message 6 of 13
Anonymous
in reply to: Anonymous

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.

Message 7 of 13
Anonymous
in reply to: Anonymous

 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

Message 8 of 13
Anonymous
in reply to: Anonymous

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.

 

Message 9 of 13
Anonymous
in reply to: Anonymous

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

Message 10 of 13
Anonymous
in reply to: Anonymous

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

Message 11 of 13
Anonymous
in reply to: Anonymous

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.

 

 

 

Message 12 of 13
Anonymous
in reply to: Anonymous

am i supposed to call .Dispose on my objects or does the system do that when they go out of scope?

thanks

mark

Message 13 of 13
Anonymous
in reply to: Anonymous

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.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost