Groups | Blog | Home
all groups > dotnet component services > june 2006 >

dotnet component services : The object that wouldn't die


Paul Taylor
6/1/2006 12:45:28 PM
I have a COM+ application with one object that is never destroyed. Each time
I run the client application that uses it, the a new instance of the object
is created. Even though the object is set to null by the client, it never
gets garbage collected. The only way to destroy the object instances that
have accumulated during sucessive runs is to shut down the application in
the Component Services snap-in.

But, this only happens when running on Win2003. Running the application on a
2000 or XP box, it works fine. I have found one other reference to this in
an archive of this newsgroup (see
http://www.dotnet247.com/247reference//msgs/53/267739.aspx).

Does anyone know what causes this, and is a solution to it known?

Paul Taylor

Paul Taylor
6/13/2006 2:40:05 PM
Below is code to demonstrate the problem.=20

Create a VS solution with three projects:
a.. a Class Library called NeverDies to contain Immortal.vb,=20
b.. a Console app called Client to contain Module1.vb=20
c.. a setup program to deploy the app to a Windows 2003 server.
Note that the Finalize method in the Immortal class contains code to =
show whether the object gets garbage collected (it doesn't).
a.. Deploy the application to a W2K3 server=20
b.. Open the Component Services snap-in
c.. Open a trace viewer application (download a freeware version of =
DebugView if required from http://www.sysinternals.com/)
d.. run Client.exe (this may cause an error on the first run)
e.. refresh the COM+ Applications node and open the properties dialog =
for the NeverDies application
f.. if you got an error when running client.exe, set the application's =
Identity to the LocalService account,=20
g.. on the Advanced tab, select "Leave running when idle"
h.. OK the changes, select the components node underneath the =
NeverDies application and switch the snap-in to Status view
i.. if you got an error first time round, run client.exe again
j.. observe that the Immortal object has not been destroyed
k.. observe that the Finalize method produced no output in the Trace =
Viewer, demonstrating that the object was not garbage collected

*********************
Immortal.vb
*********************
Imports System.Threading
Imports System.EnterpriseServices

<EventTrackingEnabled()> _
Public Class Immortal
Inherits ServicedComponent

Private _start As DateTime

Public Sub New()
_start =3D Now
End Sub

Public Function Live() As Long
Dim rnd As New Random
Thread.CurrentThread.Sleep(rnd.Next(1, 3000))
Return Now.Subtract(_start).TotalMilliseconds
End Function

Protected Overrides Sub Finalize()
Trace.WriteLine("Finalized")
MyBase.Finalize()
End Sub

End Class

*********************
Add the following attributes to AssemblyInfo.vb in NeverDies project
*********************
<Assembly: ApplicationName("NeverDies")>=20
<Assembly: ApplicationID("{49CC81DB-C910-40ec-B5DA-DADF6DFDE917}")>=20
<Assembly: ApplicationActivation(ActivationOption.Server)>=20
<Assembly: ApplicationAccessControl(False)>=20


*********************
Module1.vb
*********************
Imports NeverDies
Imports System.EnterpriseServices


Module Module1
Sub Main()
Dim imm As New NeverDies.Immortal
Dim iLifeSpan As Integer =3D imm.Live()
imm =3D Nothing
'Force garbage collection
System.GC.Collect()
Console.WriteLine(String.Format("The object lived for {0} =
milliseconds", iLifeSpan))
Console.WriteLine("Press a key to continue...")
Console.Read()
End Sub
Simon Hart
6/18/2006 9:33:02 PM
You need to dispose the server object, setting it to null will not =
release it.

Regards
Simon.
[quoted text, click to view]
Below is code to demonstrate the problem.=20

Create a VS solution with three projects:
a.. a Class Library called NeverDies to contain Immortal.vb,=20
b.. a Console app called Client to contain Module1.vb=20
c.. a setup program to deploy the app to a Windows 2003 server.
Note that the Finalize method in the Immortal class contains code to =
show whether the object gets garbage collected (it doesn't).
a.. Deploy the application to a W2K3 server=20
b.. Open the Component Services snap-in=20
c.. Open a trace viewer application (download a freeware version of =
DebugView if required from http://www.sysinternals.com/)=20
d.. run Client.exe (this may cause an error on the first run)=20
e.. refresh the COM+ Applications node and open the properties =
dialog for the NeverDies application=20
f.. if you got an error when running client.exe, set the =
application's Identity to the LocalService account,=20
g.. on the Advanced tab, select "Leave running when idle"=20
h.. OK the changes, select the components node underneath the =
NeverDies application and switch the snap-in to Status view=20
i.. if you got an error first time round, run client.exe again=20
j.. observe that the Immortal object has not been destroyed=20
k.. observe that the Finalize method produced no output in the Trace =
Viewer, demonstrating that the object was not garbage collected

*********************
Immortal.vb
*********************
Imports System.Threading
Imports System.EnterpriseServices

<EventTrackingEnabled()> _
Public Class Immortal
Inherits ServicedComponent

Private _start As DateTime

Public Sub New()
_start =3D Now
End Sub

Public Function Live() As Long
Dim rnd As New Random
Thread.CurrentThread.Sleep(rnd.Next(1, 3000))
Return Now.Subtract(_start).TotalMilliseconds
End Function

Protected Overrides Sub Finalize()
Trace.WriteLine("Finalized")
MyBase.Finalize()
End Sub

End Class

*********************
Add the following attributes to AssemblyInfo.vb in NeverDies project
*********************
<Assembly: ApplicationName("NeverDies")>=20
<Assembly: ApplicationID("{49CC81DB-C910-40ec-B5DA-DADF6DFDE917}")>=20
<Assembly: ApplicationActivation(ActivationOption.Server)>=20
<Assembly: ApplicationAccessControl(False)>=20


*********************
Module1.vb
*********************
Imports NeverDies
Imports System.EnterpriseServices


Module Module1
Sub Main()
Dim imm As New NeverDies.Immortal
Dim iLifeSpan As Integer =3D imm.Live()
imm =3D Nothing
'Force garbage collection
System.GC.Collect()
Console.WriteLine(String.Format("The object lived for {0} =
milliseconds", iLifeSpan))
Console.WriteLine("Press a key to continue...")
Console.Read()
End Sub
Paul Taylor
6/19/2006 12:00:00 AM
Thanks Simon, that does the trick. I was surprised - I didn't =
implemented a Dispose method on the object as it doesn't use any =
unmanaged resources. It must be the base class (ServicedComponent) that =
requires to be Disposed before it can be released. I guess it must =
create an external reference to itself in COM+ that prevents it from =
being garbage collected. Some clear documentation from Microsoft about =
this would be welcome.

Paul
[quoted text, click to view]
You need to dispose the server object, setting it to null will not =
release it.

Regards
Simon.
[quoted text, click to view]
Below is code to demonstrate the problem.=20

Create a VS solution with three projects:
a.. a Class Library called NeverDies to contain Immortal.vb,=20
b.. a Console app called Client to contain Module1.vb=20
c.. a setup program to deploy the app to a Windows 2003 server.
Note that the Finalize method in the Immortal class contains code to =
show whether the object gets garbage collected (it doesn't).
a.. Deploy the application to a W2K3 server=20
b.. Open the Component Services snap-in=20
c.. Open a trace viewer application (download a freeware version =
of DebugView if required from http://www.sysinternals.com/)=20
d.. run Client.exe (this may cause an error on the first run)=20
e.. refresh the COM+ Applications node and open the properties =
dialog for the NeverDies application=20
f.. if you got an error when running client.exe, set the =
application's Identity to the LocalService account,=20
g.. on the Advanced tab, select "Leave running when idle"=20
h.. OK the changes, select the components node underneath the =
NeverDies application and switch the snap-in to Status view=20
i.. if you got an error first time round, run client.exe again=20
j.. observe that the Immortal object has not been destroyed=20
k.. observe that the Finalize method produced no output in the =
Trace Viewer, demonstrating that the object was not garbage collected

*********************
Immortal.vb
*********************
Imports System.Threading
Imports System.EnterpriseServices

<EventTrackingEnabled()> _
Public Class Immortal
Inherits ServicedComponent

Private _start As DateTime

Public Sub New()
_start =3D Now
End Sub

Public Function Live() As Long
Dim rnd As New Random
Thread.CurrentThread.Sleep(rnd.Next(1, 3000))
Return Now.Subtract(_start).TotalMilliseconds
End Function

Protected Overrides Sub Finalize()
Trace.WriteLine("Finalized")
MyBase.Finalize()
End Sub

End Class

*********************
Add the following attributes to AssemblyInfo.vb in NeverDies project
*********************
<Assembly: ApplicationName("NeverDies")>=20
<Assembly: ApplicationID("{49CC81DB-C910-40ec-B5DA-DADF6DFDE917}")>=20
<Assembly: ApplicationActivation(ActivationOption.Server)>=20
<Assembly: ApplicationAccessControl(False)>=20


*********************
Module1.vb
*********************
Imports NeverDies
Imports System.EnterpriseServices


Module Module1
Sub Main()
Dim imm As New NeverDies.Immortal
Dim iLifeSpan As Integer =3D imm.Live()
imm =3D Nothing
'Force garbage collection
System.GC.Collect()
Console.WriteLine(String.Format("The object lived for {0} =
milliseconds", iLifeSpan))
Console.WriteLine("Press a key to continue...")
Console.Read()
End Sub
Stan
7/5/2006 8:20:02 AM
I am not sure you guys are still out there, but where did you add the
dispose? I've a similar problem with a VB6.0 dll in COM+ pack A calling a
..NET Serviced Component in COM+ pack B. THe counters in B just keep
increasing, and never go down. In my scenario I am unsure where I would put
a dispose? Did you mean my serviced component needs to implement a dispose
or the VB app somehow(???) should call dispose.

Stan

[quoted text, click to view]
AddThis Social Bookmark Button