I have a COM object that reads and writes data. I need to read and write using the COM object as fast as possible.
while(!stopLoop)
{
DateTime t1;
foreach(Item in Data)
{
ReadData(...);
//...
}
DateTime t2;
TimeSpan loopTime = t2 - t1;
}
I've wrote some code and ran it. At first I have a loopTime
of 200ms but it got slower and slower, after 45 minutes it took around 3 seconds. The memory usage doubled in the same time.
I checked with VMMap and: over time only the non-managed heap memory increased. So I guess I have a memory leak in the COM object.
Okay, googled it and tried following:
System.Runtime.InteropServices.Marshal.ReleaseComObject(myObject);
After creating a new object and initialization I could read again:
antiLeakCounter = 0; //as proposed in the comments by Hans Passant
public object ReadData(...)
{
object obj = new object();
myComObj.Read(..., ref obj);
if(++antiLeakCounter == 100)
{
//TryRemoveLeak();
antiLeakCounter = 0;
}
return obj;
}
private void TryRemoveLeak()
{
ReleaseComObject(myComObj);
myComObj = new MyComClass();
InitMyComObj();
}
With ReleaseObject I get a continous time again. I am not sure if the COM object works now.
myComObj.Read(..., ref obj);
normally returns the ref object that I can check with is bool
/byte[]
/int
, but after ReleaseComObject
and recreation the ref object only returns object
so I cannot cast it now. So... there must be something wrong with my recreation.
How can I recreate my COM object properly? Or is there a different way to prevent these leaks?
Edit:
I tested with GC.Collect, AddMemoryPressure, etc. but can't get the loop time stable:
private void TryRemoveLeak()
{
//instead of ReleaseComObject...
}
Test 1:
GC.Collect();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect(GC.GetGeneration(myComObj), GCCollectionMode.Optimized);
Test 4:
public object ReadData(...)
{
object obj = new object();
GC.AddMemoryPressure(byteSizeOfObj);
myComObj.Read(..., ref obj);
GC.RemoveMemoryPressure(byteSizeOfObj); //after returning, the obj is dead, right?
return obj;
}
The COM object interacts with another application called PLCSIM.
MyApplication <-COM-> PLCSIM
I checked PLCSIM and can see a memory leak too. It's leaking nearly the same amount like my application in the same time.