Dispose of COM

A

andrew lowe

Hi,

I have a web service that calls a COM object written in Uniface and
unfortunatley we don't have the opportunity to rewrite this component. This
COM object is not thread safe, in fact when two threads access the object it
will fail spectactularly! This is fine, I have created a class that only
allows one thread to call into the COM object at a time. The esyv0005Class
is the .NET Interop assembly created from our COM object.

internal class RequestBroker {
private static object mLock = new object();

........... more methods

private string InternalExecute(string parameters, string serviceName) {
lock (mLock) {
string resultXml;
ePathway.Request.Broker.esyv0005Class service = new
ePathway.Request.Broker.esyv0005Class();
service.exec(serviceName, parameters, out resultXml);

// The important lines here
// service = null;
// GC.Collect();

return resultXml;
}
}
}

If i leave the two lines commented out we rely on the GC to at its leisure
dispose of the interop object which intern will free the reference to the
underlying COM object. The problem with this is that our application fails
when stress tested because the object isn't being disposed of immediately
and we receive a dreaded Uniface -57 error. If I uncomment the calls to
GC.Collect() i then have a hell of alot of calls for the GC to do its thing,
especially underload.

Now the .Net interop class (esyv005Class) doesn't implement IDispose so
thats not a solution here, is there a way of having the interop object GC
immediately without the overhead of calling GC.Collect() ? I have tried
making the variable a member of the class and only instantiating the object
once, thereby eliminating the need to dispose of the object, however I
encountered periodic errors. Any other alternatives that you can see ?

tia
andrew
 
F

Frank Oquendo

andrew said:
is there a way of having the interop
object GC immediately without the overhead of calling GC.Collect() ?

No but even so, simply setting your reference to null is not enough to
ensure it does get collected. Be sure to call
System.Runtime.IntropServices.Marshal.ReleaseComObject first in order to
decrement the reference count on the ComObject itself.

You might also consider implementing IDispose on the object's container.
In the Dispose method, check to if the object is set to null. If not,
release it then set it to null.

--
There are 10 kinds of people. Those who understand binary and those who
don't.

http://code.acadx.com
(Pull the pin to reply)
 
A

andrew lowe

Frank Oquendo said:
No but even so, simply setting your reference to null is not enough to
ensure it does get collected. Be sure to call
System.Runtime.IntropServices.Marshal.ReleaseComObject first in order to
decrement the reference count on the ComObject itself.

Thanks Frank, that solves the problem without having to call GC.Collect(),
you beauty

andrew
 
E

Eric Newton

Frank's reply is a good one... You actually have a component that represents
a finite (in general terms) resource, "Uniface"

Normally one should implement IDisposable on these classes to "inform" users
of the class that the Dispose method should be called before releasing the
reference.

Your code looks good to me, to prevent that re-entrancy problem, and Frank's
suggestion will help manage the "finite resource".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top