Optimize Idle Time Management for Server Applications

COM+ shuts down the host process (Dllhost.exe) after a configured period of inactivity (the idle time) from any client. By default, the process stays in memory for three minutes if there are no clients using the application. To optimize idle time management:

Consider increasing the idle time if clients tend to access components in short, sharp intervals in between lengthy periods of idle time. This will reduce the number of process restarts.

If your application contains a pool of objects, leave the process running idle to avoid having to repopulate the object pool. If you expect your component to be called every ten minutes, increase the idle time to a slightly longer time. For example, set it to twelve minutes.

To configure the idle time, use the Advanced page of the application's Properties dialog box in Component Services. Values in the range 1–1440 minutes are supported.

Always Call Dispose

Client code that calls serviced components must always call the object's Dispose method as soon as it is finished using it. Setting the object reference to null or Nothing is not adequate. If you do not call Dispose, unmanaged resources must go through finalization which is less efficient and more resource intensive. Clients that do not call Dispose can cause activity deadlock in multithreaded applications due to the asynchronous cleanup of object references. If you do not call Dispose on pooled objects that do not use JIT activation, the pooled objects are not returned to the pool until they go through finalization and garbage collection. By calling Dispose, you efficiently release the unmanaged resources (such as COM objects) used by the serviced component and reduce memory utilization.

DisableAsyncFinalization Registry Setting

If your managed client code does not call Dispose to release managed serviced components and you cannot change the client source code, as a last resort you can consider using the DisableAsyncFinalization registry key. This key prevents the serviced component infrastructure from co-opting user threads to help out with cleanup (leaving all the work to the finalizer thread).

If You Call COM Components, Consider Calling ReleaseComObject

Consider calling ReleaseComObject if you call COM components. Examples include hosting COM objects in COM+ and calling them from Enterprise Services or calling them directly from a managed client, such as ASP.NET. Marshal.ReleaseComObject helps release the COM object as soon as possible. Under load, garbage collection (and finalization) might not occur soon enough and performance might suffer.

ReleaseComObject decrements the reference count of the RCW, which itself maintains a reference count on the underlying COM object. When the RCW's internal reference count goes to zero, the underlying COM object is released.

Marshal.Release

Calling the Marshal.Release method is unnecessary unless you manually manage object lifetime using Marshal.AddRef. It is also applicable when you call Marshal.GetComInterfaceForObject, Marshal.GetIUnknownForObject, or Marshal.GetIDispatchForObject to obtain an IUnknown interface pointer.

Summary of Dispose, ReleaseComObject, and Release Guidelines

You should only call ReleaseComObject where your managed code references an unmanaged COM+ component. In this instance, the unmanaged COM+ component will not provide a Dispose method. In cases where managed client code references a managed serviced component, the client code can and should call Dispose to force the release of unmanaged resources because all managed serviced components implement IDisposable. Table 8.4 summarizes when you need to call ReleaseComObject.

Client

Server

Call Dispose

Call ReleaseComObject

Call IUnknown Release

Managed

Managed component using ES

Yes

No

No

Managed

Unmanaged component using COM+

No

Yes

No

Unmanaged

Managed component using ES

Yes

No

Yes

Unmanaged

Unmanaged component using COM+

No

No

Yes

Table 8.4 When to Call Dispose, ReleaseComObject, and IUnknown.Release

Note that unmanaged code should always call IUnknown.Release. If unmanaged code references a managed component using Enterprise Services, it should also first call Dispose on the COM Callable Wrapper (CCW) through which it communicates with the managed object. If unmanaged code references an unmanaged COM+ component, it simply calls IUnknown.Release.