COM+ object not being released back to the pool

  • Thread starter Thread starter VinDotNet
  • Start date Start date
V

VinDotNet

Here's the Scenario I am facing:
I've got a winform managed c++ client which connects to my managed
COM+ server application (by making createinstance, then typecasting
the object to an interface, then calling methods over it). This COM+
server application is from a C# dll that has references to Interop dlls

(com type libraries written in unmanaged c++) and MC++ wrappers over
unmanaged c++ code. I've got object pooling enabled with (Min : 0 and
Max : 1048576). I've got a db connection in the construct() method of
the servicedcomponent.


I am on
1. VS.Net 2003
2. .Net framework 1.1
3. COM+ is a server application with JIT disabled, object pooling
enabled.


Issue:
When I run the winform client for the first time, everything goes well.

But when I close it the object stays there and isn't released back to
the pool. I mean in the component services mmc, event statistics i can
see Objects: 1 Activated: 1 Pooled: 1.


If I invoke my COM+ component from a vbscript, C# client, unmanaged c++

client (by cocreateinstance()) the objects are being returned back to
the pool properly. Point to note here is I don't even call the
ServicedComponent.DisposeObjec­t() at client.
Whereas it doesn't work in my above scenario (winform managed c++)
client even after I do a disposeobject or Marshal.ReleaseComObject().


No matter what, the objects keep on growing as many no of clients
getting connected.


1. How to make them released back to the pool immediately as the client

is closed? or what am I doing wrong here?


Could you please help me out to resolve this issue. I've searched over
the web everywhere, read many of answers to these kind of
questions in newsgroups, tried various options, but I am yet to find a
solution.
Here's a list of options I tried and couldn't succeed.
1. ServicedComponent.DisposeObjec­t(obj); at the client.
2. Called Marshal.ReleaseComObject(inter­op object) at the
client.
Released all com objects.
3. ServicedComponent.DisposeObjec­t(this); at the server, just
after
deactivate() and disconnect().
4. Called Marshal.ReleaseComObject(inter­op object) at the
server.
Released all com objects.
5. Deactivate() was not getting called when winform client
closes. So
I tried forcibly calling it from server's disconnect method. Didn't
work.
6. Set JIT activation to true in component's properties.
7. Set Object pooling disabled in component's properties.


2. Also one more question, if my object pooling is enabled, and the
construct() method of servicedcomponent is called everytime a request
comes, does it mean object pooling is of no use here? In object
pooling, if a second request comes, isn't it not supposed to invoke
construct() and directly call activate()?


Thanks and Regards,
Vin
 
Nick, thanks for taking time to think over my query.
Yup I read the same about AutoComplete and put it over the methods in
the servicedcomponent derived class. But you know what I also read
somewhere else that If your class inherits from an interface and you
are exposing the interface methods, then its not gonna work. I am
implementing an interface in my servcomp derived class and these
methods are to be called by the com clients.

Yup I know the database connection has to be in activate() I've done
that change and its fine. But my basic problem (releasing to the pool)
is still there.

Now in my mc++ winform client, I am doing an activator.createinstance()
Then typecasting the object to the interface, then access methods on
them.
There is no other way I can create the com component, coz this part of
the code is out of my scope. I am not supposed to touch it.

Can I get some more ideas/resolutions from you?

Willy, as I said above, at the client, I do a
obj = (Imycominterface) activator.createinstance();
obj.Myservermethod();
Yup I am overriding CanBePooled() and returning true.

Thanks in advance,
Vin
 
VinDotNet said:
Nick, thanks for taking time to think over my query.
Yup I read the same about AutoComplete and put it over the methods in
the servicedcomponent derived class. But you know what I also read
somewhere else that If your class inherits from an interface and you
are exposing the interface methods, then its not gonna work. I am
implementing an interface in my servcomp derived class and these
methods are to be called by the com clients.

Yup I know the database connection has to be in activate() I've done
that change and its fine. But my basic problem (releasing to the pool)
is still there.

Now in my mc++ winform client, I am doing an activator.createinstance()
Then typecasting the object to the interface, then access methods on
them.
There is no other way I can create the com component, coz this part of
the code is out of my scope. I am not supposed to touch it.

Can I get some more ideas/resolutions from you?

Willy, as I said above, at the client, I do a
obj = (Imycominterface) activator.createinstance();
obj.Myservermethod();
Yup I am overriding CanBePooled() and returning true.

Thanks in advance,
Vin

As long as your client holds a reference to the object, the object will stay
activated. Now when the object reference gets released, that is when the
reference goes out of scope or is explicitly set to null, the object is kept
alive by it's proxy/stub pair and the COM+ object lifetime is determined by
the GC.
If you want the object to get released to the pool deterministically, you
have to call DisposeObject before you release the object reference, failing
to do this puts you at the mercy of the GC to return your objects to the
pool.
When this is done the object gets back to the pool, or is immediately
re-used by another client who had a request pending when the pool was
exhausted (max. objects reached).

So basically your client should look like this....
{
Imycominterface obj =
Activator.CreateInstance(typeof(SomeCOMPPClass)) as Imycominterface;
...
use the object
System.EnterpriseServices.ServicedComponent.DisposeObject(objas
SomeCOMPPClass)
}

CreateInstance will pull an object from the pool or create (construct) a new
one.
DisposeObject will release the proxy/stub and the COM+ infrastructure will
all or not put it back in the pool depending on the return value from
CanBePooled.
Note that when an object is picked-up from the pool that your Activate()
method is called and when it's put back in the pool that Deactivate is
called followed by a call to CanBePooled. Did you ever traced these calls?

Willy.
 
Back
Top