Microsoft KB Archive/317336

= How To Use Enterprise Services Object Pooling in Visual Basic .NET =

Article ID: 317336

Article Last Modified on 7/15/2004

-

APPLIES TO


 * Microsoft .NET Framework Class Libraries 1.0
 * Microsoft Enterprise Services (included with the .NET Framework) 1.0
 * Microsoft Visual Basic .NET 2002 Standard Edition

-



This article was previously published under Q317336



The following .NET Framework Class Library namespace is referenced in this article:

System.EnterpriseServices.ServicedComponent

IN THIS TASK
SUMMARY Requirements Create a Console Application in Visual Basic .NET Add a Poolable and a Non-Poolable Class to the Project Modify Module1.vb to Create Multiple Instances of These Classes Generate a Strong Name for the Assembly Complete Code Listings
 * Class1.vb
 * Module1.vb
 * AssemblyInfo.vb

Verify That It Works Troubleshooting REFERENCES



SUMMARY
This article demonstrates how to create a console application that uses object pooling in Visual Basic .NET. You can turn on and turn off object pooling to see how object pooling affects an application that creates many expensive objects.

back to the top

Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
 * Microsoft .NET Framework
 * Microsoft Windows 2000 Professional, Microsoft Windows 2000 Server, Microsoft Windows XP Professional, or Microsoft Windows XP Server

This article assumes that you are familiar with the following topics:
 * Component Object Model (COM) and Enterprise Services
 * Object pooling
 * Using attributes to extend metadata

back to the top

Create a Console Application in Visual Basic .NET
 Start Microsoft Visual Studio .NET. On the File menu, point to New, and then click New Project. In the New Project dialog box, click Visual Basic Projects under Project Types, and then click Console Application under Templates. In the Name text box, type PoolingDemo, and then click OK. Make sure that the Solution Explorer window is visible. If Solution Explorer is not visible, press the CTRL+ALT+L key combination. Follow these steps to add a reference to the COM component that you will be using:  In Solution Explorer, right-click References, and then click Add Reference.</li> On the .NET tab, click System.EnterpriseServices in the list of available components, and then click Select. Notice that System.EnterpriseServices appears in the Selected Components list.</li> Click OK. Notice that System.EnterpriseServices appears under the References node in the console application.</li></ol> </li></ol>

back to the top

Add a Poolable and a Non-Poolable Class to the Project
<ol> Right-click PoolingDemo in Solution Explorer, point to Add, and then click Add New Item.</li> In the Add New Item dialog box, click Class under Templates, and then click Open. Class1.vb is created by default and contains both poolable and non-poolable classes.</li>  To access object pooling attributes and members, add the following code to the top of Class1.vb: Imports System.EnterpriseServices </li>  Replace the default Class1 declaration with the following code: Public Class Poolable Sub New Threading.Thread.Sleep(500) End Sub Public Sub DoSomething ' Add method contents here. End Sub End Class Notice that the constructor contains code that simulates an expensive operation. </li>  The object must inherit the ServicedComponent class to come under the control of the Component Services runtime. Add the following code after the class declaration: Inherits ServicedComponent </li> To make this class poolable, follow these steps: <ol style="list-style-type: lower-alpha;">  The ObjectPoolingAttribute attribute, which is saved with the metadata of the class file, flags the object for pooling at run time. Add the following code above the Class declaration to add the ObjectPoolingAttribute attribute to the class: <ObjectPooling(MinPoolSize:=0, MaxPoolSize:=1), JustInTimeActivation(True)> _ NOTE: Although the JustInTimeActivation attribute is not required to enable pooling, you may want to use this attribute in most cases. Because it is expensive to create and to discard components, you can improve performance significantly by allowing multiple clients to reuse component instances. </li>  The CanBePooledServicedComponent method returns False by default. To override the CanBePooled method so that the method returns True, add the following code: Protected Overrides Function CanBePooled As Boolean Return True End Function </li></ol> </li>  Add the following code to the non-poolable class: Public Class NonPoolable Inherits ServicedComponent Sub New ' Simulate an expensive operation. Threading.Thread.Sleep(500) End Sub Public Sub DoSomething ' Add method contents here. End Sub End Class </li></ol>

back to the top

Modify Module1.vb to Create Multiple Instances of These Classes
<ol> In the Code Editor window, click the Module1.vb tab.</li>  At the top of the file, add the following Imports statement for the EnterpriseServices namespace to allow access to the DisposeObject method: Imports System.EnterpriseServices The DisposeOjbect method returns objects to the object pool, which allows them to be reused. </li>  Add the following Sub Main procedure: Sub Main Dim StartTime As DateTime = DateTime.Now Dim i As Int32

Const Iterations As Int16 = 50 For i = 1 To Iterations Dim D As New NonPoolable

D.DoSomething ServicedComponent.DisposeObject(D) Next

Dim EndTime As DateTime = DateTime.Now Dim Elapsed As TimeSpan = EndTime.Subtract(StartTime) Dim OperationsPerSecond = Iterations / Elapsed.TotalSeconds

Console.WriteLine(&quot;Object Creations / Second = &quot; & OperationsPerSecond) System.Console.ReadLine End Sub This code sets up a loop that creates an instance of the NonPoolable or the Poolable class during each of its 50 iterations. The code records the start and the end times for the loop and then writes the number of objects that are created per second to the console. </li></ol>

back to the top

Generate a Strong Name for the Assembly
You must generate a strong name for the assembly that this project will generate. Without a strong name, you cannot use COM+ services to register this assembly.

To generate this cryptographic key pair, use the Strong Name (Sn.exe) tool, which is located in the Bin folder where the .NET Framework Software Development Kit (SDK) is installed. Use the following command-line syntax to run the Sn.exe tool:

sn -k \ \ .snk

<ol> To open a Visual Studio .NET command prompt, click Start, point to Programs, point to Microsoft Visual Studio .NET, point to Visual Studio .NET Tools, and then click Visual Studio .NET Command Prompt.</li> <li>At the command prompt, type the following command:

sn -k :\ \poolkey.snk

</li> <li>Press the ENTER key to generate the key pair. Notice that the following message appears in the command window:

Key pair written to...

</li> <li> To associate this key with the project's assembly, double-click AssemblyInfo.vb in Solution Explorer. By default, Visual Studio .NET includes assembly attributes in this file when you create a project. Add the following code to this list of assembly attributes: <Assembly: AssemblyKeyFile(&quot;..\..\poolkey.snk&quot;)> </li></ol>

back to the top

Class1.vb
Imports System.EnterpriseServices

<ObjectPooling(MinPoolSize:=0, MaxPoolSize:=1), JustInTimeActivation(True)> _ Public Class Poolable Inherits ServicedComponent Sub New ' Simulate an expensive operation. Threading.Thread.Sleep(500) End Sub

Public Sub DoSomething ' Add method contents here. End Sub

Protected Overrides Function CanBePooled As Boolean Return True End Function End Class

Public Class NonPoolable Inherits ServicedComponent Sub New ' Simulate an expensive operation. Threading.Thread.Sleep(500) End Sub

Public Sub DoSomething ' Add method contents here. End Sub End Class back to the top

Module1.vb
Imports System.EnterpriseServices

Module Module1

Sub Main Dim StartTime As DateTime = DateTime.Now Dim i As Int32

Const Iterations As Int16 = 50 For i = 1 To Iterations 'Dim D As New Poolable Dim D As New NonPoolable

D.DoSomething ' To return the object to the object pool, use DisposeObject. ' This allows the object to be reused from the pool. If you do not call ' DisposeObject, the garbage collector does not collect this object, ' and the object is not reused from the object pool. ServicedComponent.DisposeObject(D) Next

Dim EndTime As DateTime = DateTime.Now Dim Elapsed As TimeSpan = EndTime.Subtract(StartTime) Dim OperationsPerSecond = Iterations / Elapsed.TotalSeconds

Console.WriteLine(&quot;Object Creations / Second = &quot; & OperationsPerSecond) ' Pause until the user presses ENTER. System.Console.ReadLine End Sub

End Module back to the top

AssemblyInfo.vb
Imports System.Reflection Imports System.Runtime.InteropServices

' The following set of attributes control general information about an assembly. ' Change these attribute values to modify the information that is associated with an assembly.

' Review the values of the assembly attributes.

<Assembly: AssemblyTitle(&quot;&quot;)> <Assembly: AssemblyDescription(&quot;&quot;)> <Assembly: AssemblyCompany(&quot;&quot;)> <Assembly: AssemblyProduct(&quot;&quot;)> <Assembly: AssemblyCopyright(&quot;&quot;)> <Assembly: AssemblyTrademark(&quot;&quot;)> <Assembly: CLSCompliant(True)> <Assembly: AssemblyKeyFile(&quot;..\..\poolkey.snk&quot;)>

'The following GUID is for the ID of the TypeLib if you expose this project to COM. <Assembly: Guid(&quot;30324ED6-329C-4B12-BDA2-8E817F1E2079&quot;)>

' Version information for an assembly consists of the following four values: ' '     Major Version '     Minor Version '     Build Number '     Revision ' ' You can specify all of these values, or you can use the asterisk (*) for ' the Build Number and the Revision values.

<Assembly: AssemblyVersion(&quot;1.0.*&quot;)> back to the top

Verify That It Works
<ol> <li>Press the F5 key to run the application in debug mode. Notice that this creates instances of the NonPoolable class.</li> <li>Wait approximately 25 seconds. Notice that the following message appears:

Object Creations / Second = 1.73542243764044

NOTE: The exact number of creations per second may vary.</li> <li>Press ENTER to exit the console application and to return to Visual Studio .NET.</li> <li> Modify Module1.vb to create instances of the Poolable class. Change the first line in the Sub Main procedure as follows: Dim D As New Poolable </li> <li>Press F5 to run the application again.</li> <li>Wait a few seconds. Notice that the following message (or similar) appears:

Object Creations / Second = 29.1977213631085

Note the significant improvement in performance when you use object pooling.</li> <li>Press ENTER to exit the console application and to return to Visual Studio .NET.</li></ol>

back to the top

Troubleshooting
Do not forget to override CanBePooled. If you omit this step, you cannot pool the object.

back to the top