i have a utility class that gets a reference to acad and acaddoc
this class hands the refs off to the classes that use them
when the app terminates i think i need to dispose of acad...
from tony he mentioned implementing idisposable but i'm not getting the syntax right
can anyone help?
<System.Runtime.InteropServices.ComVisible(False)> Public Class MCSUtil
Implements IDisposable
Private m_acadDoc As AcadDocument
Private m_AcadApp As Autodesk.AutoCAD.Interop.AcadApplication = Nothing
Sub Dispose()
m_AcadApp = Nothing
m_acadDoc = Nothing
End Sub
that sub dispose isn't recognized as the dispose for IDisposable...how do i do that?
thanks
mark
Interface methods must be declared as Public.
If your class is running in another process, you don't need to
'dispose' acad. You can call Marshal.ReleaseComObject() to
release the reference to COM objects, but that will happen
anyway when your application terminates or when the next
garbage collection occurs after setting all variables that are
referencing the COM object to Nothing.
well it's driving me crazy why i can't get acad to close after running a dotnet app i'm testing
i don't know what else to try and apparently no one else has this problem.
i netload the dll, run, close acad, edit some changes in the vbproj, rebuild dll, get error cant' rewrite dll because another process has it open...look in task mgr and there's acad sitting there doing nothing but not closing.
grrrr
this doesn't happen every time but most times and it's about to drive me over the edge
🙂
thanks
mark
Why don't you just call AcadApplication.Quit() ?
I don't want to quit acad in my application. I'm only closing it because i'm editing the app and need to close acad to rebuild the dll
Don't know if this'll help but I had a similar problem when automating Excel in my AutoCAD app. No matter what I did there was always an Excel process hanging around. I eventually discovered that it was because I had a variable that was still linked to an excel object that I hadn't disposed of (it was a variable I'd assigned the current worksheet to). Sloppy I know but I never said I was any good at this coding lark!
I'd say perhaps check that you don't have any variables that are still holding acad objects. If they're all gone then Tony's suggestion about the Marshal.ReleaseComObject should work (at least it worked for me).
hth
I'll check that, but according to several posts here in past when a sub ends the variable goes out of scope so at program end nothing should still be alive. ... emphasis on "Should" ..
also per previous posts from Tony, the .ReleaseComobject "should' not be necessary when run in acad process space...
it sure won't hurt to try though
i'll have to figure out where that goes in my code
Would I be correct in saying that the only time that Marshal.ReleaseComObject() would really be required for a dll running in-process in autocad would be if the COM object holds a resource (file...etc) that you need released before futher code execution? -Chris
A COM object assigned to a variable will not be released when the
variable goes out of scope. It will be released when the next
garbage collection occurs, which could be any time after the
variable has gone out of scope. If the COM object is in the same
process as the code that uses it, then there is no issue with
releasing it, because it will not prevent the app from closing if
it is not released.
ReleaseComObject() releases a COM object determinstically,
which in the case of using COM objects from the same process,
is usually not required. The notable exception is AxDbDocument,
because releasing it releases the lock on the DWG file.
A COM object will eventually be released during a GC, when
there are no longer any reachable references to it, if calls
to ReleaseComObject()/FinalReleaseComObject() are not
made.
@chrisshoemaker4224 wrote:Would I be correct in saying that the only time that Marshal.ReleaseComObject() would really be required for a dll running in-process in autocad would be if the COM object holds a resource (file...etc) that you need released before futher code execution? -Chris
One of the most overlooked reasons for objects not being disposed was cited by Tony.
"A COM object will eventually be released during a GC, when there are no longer any reachable references to it, ..."
The key phrase here is reachable references. One of the mot common examples of an overlooked reachable reference is the InvocationList of an event delegate. When you subscribe to an object's event, you create a reference to that object. In most cases this is not a problem. A WinForm is a typical non-problem. At least most of the time. But, .....
If a class subscribes to events from an object declared and instantiated by an external class, then this can create a problem scenario. Consider what happens if the publishing object has a longer lifetime than the subscriber. A typical WinForm can declare controls, and subscribe to events. When the form is closed, the declared controls are disposed. Their InvocationLists point to methods on the form, which is being disposed. Good.
But when the publisher is alive after the subscriber is made a candidate for the GC, guess what? You got it. The faithful GC sees a reachable reference from the publisher, and does not fully dispose of the subscriber object. Again, from Tony.
"A COM object assigned to a variable will not be released when the variable goes out of scope. It will be released when the next garbage collection occurs, which could be any time after the variable has gone out of scope.
If the COM object is in the same process as the code that uses it, then there is no issue with releasing it, because it will not prevent the app from closing if it is not released."
The target methods on the publisher's InvocationList are still alive and well. The event handlers in the disposal candidate's InvocationList are still in scope! The GC will not dispose of the object until the publishing object gets disposed. That second sentence describes the scenario of a WinForm disposing of its own controls pretty accurately.
The subscriber will not get disposed until it unsubscribes from the publisher. Moral of the story is this. When implementing IDisposable, make sure to unsubscribe to event associated with objects defined and declared by external classes.
Hope this helps.
Rudy =8^D
Ah...that explains it. I was calling ReleaseComObject in the dispose methods of other classes just because I read some else (non ACAD-specific) that you should though it seemed to work fine one way or the other. AxDbDocument is where I did run into some trouble with locked files because DWG files weren't being unlocked consistantly. As it turns out i've re-writting most of the AxDbDocument functionality using the managed libraries so i't become less of issue, but the whole thing makes a lot more sense now. Thanks all!
@mpropst wrote:well it's driving me crazy why i can't get acad to close after running a dotnet app i'm testing
i don't know what else to try and apparently no one else has this problem.
i netload the dll, run, close acad, edit some changes in the vbproj, rebuild dll, get error cant' rewrite dll because another process has it open...look in task mgr and there's acad sitting there doing nothing but not closing.
grrrr
this doesn't happen every time but most times and it's about to drive me over the edge
🙂
thanks
mark
Are you using any threads? Are they still running after your application has "closed"? That is the prime scenario whereby a DLL can still "be in use" after the application has closed.
Rudy =8^D
COM objects generally do not handle managed events directly,
so it would be extremely and unusually rare to find references
to them in a Delegate's callback chain.
What about .NET wrappers around COM objects?
As I look through the API, I am starting to see a lot of wrappers around COM. DisposableWrapper is a base class for Entity. DisposableWrapper is everywhere. It wraps MarshalByRefObject. It is also a base class for Document, Transaction, Window, etc.
DisposableWrapper doesn't wrap COM objects, it wraps native C++ objects.