|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
OverviewSuppose you have an existing COM component implemented in VC++ or VB. You have been using it in your desktop applications without any problem. Now you need the same functionality in your .NET projects. You could spend time to reimplement the component using C# or VB.NET but sometimes this approach is not always an ideal one. For example, there could be a lot of Win32 API calls or calls to some other third-party C library in the old version, it might not be easily implemented using C#. Even worse, the component could be written by someone else who already left the company (and took the expertise with him), or it could be a third-party component with no source code. Fortunately, it is not hard to use COM components directly in .NET projects. There have been some good articles talking about this, I just want to briefly summarize what you have to do in order to use a COM component from .NET projects: First you need to install and register the COM component, then you need to add a reference to the COM component in your .NET projects. .NET will automatically generate a "wrapper" dll for you. Let's see a simple example. I have included with this article a DummyCom.dll written with VC++/ATL which implements a simple COM object called DummyObj. This COM object has only one method called Test. The method takes an input string and returns an output string. The output string indicates the date/time the object was created and the date/time the method was called as well as the input string passed into the method. Here is C# sample code that calls the Test method of DummyObj. using DUMMYCOMLIB;
...
DummyObj obj = new DummyObj();
String sOutput = obj.Test("this is a test");
...
Here is what the output string looks like: Object created at '2003-06-13, 11:06:18'
'Test' method called at '2003-06-13, 11:06:18' with input 'this is a test'
If it was always this easy then I wouldn't need to write this article. There are some potential problems which I will try to address below.
The ProblemsSuppose the above sample code is cut from the code behind file of a web (aspx) page. As we can see the COM object reference is assigned to a local variable. After the code is executed, the reference is gone and there is no way to get back to the same instance of the COM object again. For each web request, the above code will create a new COM object. This may not be an issue for many COM objects; however, some COM objects may have to do heavy one-time initialization work before they can be used. For example, when the object in question is created, it may need to access a remote database to fetch data for later use. So it may be preferable to keep the reference to the COM object and reuse it in multiple web requests.Ok, that's easy. All we have to do is use a static member variable of the current class to hold the COM object and use it in all web requests. In case you don't know, the static (or Shared for VB.NET) keyword means that this member variable is global and you don't need to create an instance of the class in order to access it. There are still problems with this approach, however. First of all, the COM object in question may not be thread-safe at the instance level. If multiple web requests are using the same instance, it may crash the server machine. Secondly, even if the COM obj is thread-safe, the performance may be bad if there is only one instance to serve all web requests. For example, the threading model for the COM object may be "apartment", which implies that only one thread can use it at any given time, all the other threads will have to wait for their turn. Apparently, we need a different approach to solve these problems
The ASP.NET Thread Pool and the ObjMan ClassASP.NET applications and ASP.NET web services use a thread pool to serve client requests. The threads in the pool will be reused for multiple requests. The number of threads in the pool will increase only when the number of simultaneous client requests increases. My solution to the above problems is create only one instance of the COM object for each thread. With my solution, the object instance for the current thread is created the first time it is needed. It is assigned a name at the time of creation and later the name string can be used to retrieve the instance for reuse. ObjMan is a VB.NET class contained in ObjectManager.dll. Here is a static method of ObjMan that is used to create and retrieve a COM object. Public Shared Function GetComObject(ByVal sObjName As String, _
ByVal sProgID As String, ByVal sServerName As String) As Object
The sObjName parameter is a user assigned name string to identify the COM object. The sProgID parameter is the prog id of the COM object. The sServerName parameter (optional) is used for creating the COM object on a remote server. The return value is a reference to the COM object for the current thread. Here is sample C# code that calls this method. using DUMMYCOMLib;
...
DummyObj obj = (DummyObj)ObjectManager.ObjMan.GetComObject("MyObjName",
"DummyObj.1");
OutputBox.Text = obj.Test(InputBox.Text);
// ObjectManager.ObjMan.RemoveComObject("MyObjName");
...
When the above code is executed by threads in a thread pool, COM object DummyObj will be created only once for each thread. The GetComObject method will retrieve an existing instance if one is already created by a previous attempt within the same thread.
The method RemoveComObject is used to get rid of the COM object created by GetComObject. If you uncomment the last line of code in the above sample, then DummyObj will be created every time the code is executed. Please note that RemoveComObject only removes the COM object with given name for the current thread. You cannot create the COM object by calling GetComObject in one thread and remove it from a different thread using RemoveComObject . It is possible to create and use multiple instances of a COM object in the same thread as long as you give them different names. The implementation of the ObjMan class is simple and straightforward. Internally, the ObjMan class uses a hashtable to store data (
The Source Code and Sample ProjectsThe download file includes the ObjectManager project (theObjMan class) and the ObjectManagerTest project (an ASP.NET test program). Here is how to install and run everything:
Please note that some COM objects (including all GUI controls) cannot be used this way. I hope this article is helpful to some of you. Thanks for reading my articles and using my tools . Latest Update
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||