I know most of you are PHP/Apache guys, but I was wondering if anyone has worked with COM objects in .NET.
I have a COM object to predict tides for a tide chart and I can't seem to release all its resources. I've used System.Runtime.InteropServices.Marshal.ReleaseComObject(myObject) But it still seems to hold on to resources. I've released all variable resources as well...
Example of my code:
public static object GetCOMData() { MyCOMObject myObject = new MyCOMObject(); // Create COM object MyCOMObject.Settings settings = myObject.Settings; // Get pointer to the Settings property so I can change some formats
settings.DateFormat = "%m/%d/%Y";
object result = myObject.GetData();
ReleaseCOMObjects(ref settings); // Settings is part of COM object and is referenced, so it must be released
ReleaseCOMObjects(ref myObject); // Release the COM object
return result;
}
public static void ReleaseCOMObjects(ref object someobject) { try { int releaseObj = System.Runtime.InteropServices.Marshal.ReleaseComObject(someobject); for (int i = releaseObj; i > 0; i--) { System.Runtime.InteropServices.Marshal.ReleaseComObject(someobject); } } finally { someobject = null; } }
However, it still seems to be holding on to resources and in my processes, aspnet_wp.exe Mem Usage keeps incrementing every time I make a call to GetCOMData()...
I don't know if that makes sense to anyone, but essentially, I want to completely close/release the object and all of its resources without having to restart aspnet_wp.exe.
Any help is appriciated!
-D
I'm a bit out of my depth here, but:
If the resource consumption or initialization time of a COM object does favor one or the other life cycle approaches, be aware that using a COM object from a managed code client dramatically changes its life cycle semantics. All managed code objects are garbage collected. A managed code object only becomes eligible for garbage collection when it is no longer reachable through a reference. When you are using a COM object through COM Interop, the RCW, which is a managed code object, holds all the Interface pointers on the underlying COM object. The Finalize method in the RCW will release all of these interface pointers when the RCW is garbage collected. Unfortunately, because it's a managed object, the RCW won't be garbage collected until the garbage collector runs, which, if memory is not in short supply on your system, will likely not be until the application shuts down. http://safari.oreilly.com/013046130X/ch07
...and from reading this it sounds like you're doing the right thing anyway...so :shrug:
Thanks for the reply, Sticky.
I think I figured it out from your second link... I changed my ReleaseCOMObject method to use reflection and release all possible COM objects from the passed object and it seemed to do the trick. Mem usage went from 180,000+K to under 70,000 K (ideal) and never goes up from there.
In case anyone ever as this issue, here's my edited methods
public static object GetCOMData() { MyCOMObject myObject = new MyCOMObject(); // Create COM object
MyCOMObject.Settings settings = myObject.Settings; // Get pointer to the Settings property so I can change some formats
settings.DateFormat = "%m/%d/%Y";
object result = myObject.GetData();
object releaseobj = (object)settings;
ReleaseCOMObjects(ref settings); // Settings is part of COM object and is referenced, so it must be released
releaseobj = (object)myObject;
ReleaseCOMObjects(ref myObject); // Release the COM object
return result;
}
public static void ReleaseCOMObjects(ref object someobject) { try { Type type = someobject.GetType(); foreach (System.Reflection.PropertyInfo propinfo in type.GetProperties()) { object obj; try { obj = propinfo.GetValue(someobject, null); ReleaseCOMObjects(ref obj); } catch { try { obj = null; } catch {
}
}
finally
{
try
{
obj = null;
}
catch
{
}
}
}
}
finally
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(someobject) > 0) { };
}
catch
{
}
finally
{
try
{
someobject = null;
}
catch
{
}
}
}
}
Lots of try/catch's because you can't always set the value of a property returned by sometype.GetProperties()
Hope it helps someone else outty...
-D
System.Reflection
a favorite.
Originally posted by: poliguin System.Reflection
a favorite.
System.Reflection ROXARZ! So do Generics
I've done some really wicked, time-saving shat with them... Like dynamically generating objects.
Just because I feel like sharing, here's what I'm doing now...
/* ObjectGenerator.cs */
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Reflection;
namespace Dreamray.DataFramework.Generator { internal static class ObjectGenerator { // "invokers" is a collection of methods I want to invoke once the object's been generated internal static T Generate(Hashtable records, params string[] invokers) { T obj; try { obj = (T)typeof(T).GetConstructor(System.Type.EmptyTypes).Invoke(null);
foreach (object str in records.Keys)
{
string prop = str.ToString();
PropertyInfo propInfo = typeof(T).GetProperty(prop);
if (propInfo != null && records[prop] != DBNull.Value) propInfo.SetValue(obj, records[str], null);
}
foreach (string invoker in invokers)
{
MethodInfo methodInfo = obj.GetType().GetMethod(invoker);
if (methodInfo != null) methodInfo.Invoke(obj, null);
}
}
catch (Exception ex)
{
return default(T);
}
return obj;
}
}
}
/* DataRepository.cs */
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.SqlClient;
namespace Dreamray.DataFramework.DataAccess { public static class DataRepository { public static Hashtable GetObjects(SqlCommand _sqlcommand) { Hashtable returnval = new Hashtable(); try { string[] defaultInvokingMethods = { "MarkOld" };
// This is just a static method in another class that generates a hashtable collection from the rows returned in a database
Hashtable[] state = Utilities.DBUtility.ExecuteMultipleRowCommand(ConnectionString, _sqlcommand);
foreach (Hashtable o in state)
{
// Here's the dynamic object creation working
**T result = Generator.ObjectGenerator.Generate<T>(o, defaultInvokingMethods)**;
//NOTE: "ID" is inherited from the objects base class
returnval.Add(typeof(T).GetProperty("ID").GetValue(result, null), result);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return returnval;
}
}
}
Here's how it's use...
I have objects that mirror my database layouts. For instance, every property of my object is named the same as each column in a table. So when I grab a record, I can generate the object based on that record...
Something like this
/* Customer.cs */ using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.SqlClient;
using Dreamray.DataFramework.DataAccess;
public override Hashtable Fetch() { // NOTE SQLCommands.GetSomeCommand() is another external class that simply returns a System.Data.SqlClient.SqlCommand return DataRepository.GetObjects(SQLCommands.GetSelectCustomerCommand()); }
generically reflects
Anyhow, thanks for the pointer Sticky...
-D
hey i am new with the excel objects and i have been trying all that you have suggested but nothing really helps the excel instance is still there if u c in the task manager .. please help