Hi JC,
Thanks for posting an update about this issue.
I'd guess the most likely issues are:
* .NET COM wrappers being slow to get released. (You could call
Marshal.ReleaseComObject for the four intermediate COM objects you
access - ActiveWorkbook, .Worksheet, .Cells Range, .Cells(1,1) Range).
Don't try to release the ExcelDna.Application reference.
* Some internal Excel structures.
Excel has a few surprising behaviours that can look like memory leaks:
* There is some kind of string caching, so if you set a cell to a new
string values, Excel will internally build a table of all the strings
seen so far. I have not idea if there is a limit to the memory used in
this way.
* Excel keeps an undo stack, and some actions will cause the undo
stack to grow, which could look like a memory leak.
Neither of these cases seem to apply to what you are doing, but it is
the kind of thing that can be very difficult to track down.
You can try to see whether the memory is from the managed heap, by
adding some extra GC.Collect() calls, or checking
GC.GetTotalMemory(true). If the problem is with the COM wrappers, I
think you'd see it with this.
The .NET marshaling code allocates memory outside the .NET heap, but
that is not actually involved in your example, and is not likely to
exhibit the periodic release you see.
Another direction you can investigate is to write something similar in
VBA and check the memory.
You can get rid of Application.OnTime by making your own timer and
calling ExcelAsyncUtil.QueueMacro / .QueueuAsMacro. These should be
reliable in the sense that they will wait until Excel is ready to
process the call.
Let us know if you find anything interesting.
Regards,
Govert
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
Ensure that the Excel-DNA project continues by
making your donation -
http://excel-dna.net/support/
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
On Apr 27, 4:52 pm, JC <
w2jc...@gmail.com> wrote:
> Some updates. I profiled the above code quite a bit and confirmed that the
> memory footprint does keep increasing slowly. The good thing is that its
> memory will be released/freed after certain time.
>
> I also realized that for some reason I was on an old ExcelDna.xll
> (v0.30.3.1?) but the latest stable version is v0.30.22.1. When I switched
> to the latest one, the same thing is still observed. Memory usage increases
> slowly and gets released from time to time.
>
> Thanks,
>
>
>
>
>
>
>
> On Wednesday, April 3, 2013 10:05:49 PM UTC-4, JC wrote:
>
> > Hi Govert,
>
> > This is more or less a follow up for my old post back in 2011 (see link
> > below) when I asked you a solution for timed call.
>
> > On using native .NET System.Timer (
> >
https://groups.google.com/d/msg/exceldna/iUE7P1Be3hA/XIOhjQ3CEnEJ)
>
> > I've tried and tested timed call by *Timer *and *OnTime*. Both of them
> > works, however Timer seems more reliable since it will *not *be
> > interrupted by other things. For example with OnTime, the timed call can be
> > easily missed when I try to open or save another spreadsheet. I didn't see
> > OnTime being so unreliable like this in my current VBA implementation.
>
> > I pasted both .dna versions here, one uses Timer, another uses OnTime.
> > Both of them can use C API or COM interface to update a Cell.
>
> > The problem is that I noticed the memory used by EXCEL process will keep
> > increasing.
> > The Timer version uses more memory much faster than OnTime version.
> > i.e. EXCEL started using 40MB, kept increasing memory usage, added 4KB to
> > 12KB every a few seconds, up to 49MB within 4 hours, and keeps growing
> > slowly...
>
> > Can you please shed some light on the root cause of this memory behavior?
> > or Is that normal? Particularly for the Timer version.
> > I also found the memory usage increases more if I use more complex code.
> > That why I had to reduce the code to its simplest form, but this issue
> > seems obvious.
>
> > ---------------------------------------------------------------------
> > -------------- Timer.dna that uses Timer ----------------------------
> > ---------------------------------------------------------------------
> > -- the following version started using 40M for EXCEL prrocess, keep
> > increasing the usage,
> > -- it goes up to 49M in memory after 4 hours, and seems slowly increasing
> > ...
> > ---------------------------------------------------------------------
>
> > <DnaLibrary Name="ExcelDna Test AddIn">
> > <Project Language="VB">
> > <Reference Path="System.Windows.Forms.dll"/>
> > <![CDATA[
> > Imports System.Windows.Forms
>
> > Public Module MyTestFunctions
> > Public aTimer As System.Windows.Forms.Timer = New Timer()
> > Public i As Integer = 0
>
> > <ExcelCommand(MenuName:="&Timer", _
> > MenuText:="Start Timer")> _
> > Public Sub StartTimer()
> > 'Dim aTimer As New Timer()
> > AddHandler aTimer.Tick, AddressOf OnTimedEvent
> > ' Set the Interval to 1 second.
> > aTimer.Interval = 1000
> > aTimer.Enabled = True
> > aTimer.Start()
> > End Sub
>
> > <ExcelCommand(MenuName:="&Timer", _
> > MenuText:="Stop Timer")> _
> > Public Sub StopTimer()
> > aTimer.Enabled = False
> > aTimer.Stop()
> > End Sub
>
> > Public Sub OnTimedEvent(source As Object, e As EventArgs)
> > ' All kind of errors might occur here...
> > Try
> > 'ExcelDnaUtil.Application.Run("UpdateCell")
> > ExcelDnaUtil.Application.Run("UpdateCellByCOM")
> > Catch
> > 'What to do now...?
> > End Try
> > End Sub
>
> > ' Excel-DNA will register this as an Excel macro
> > Public Sub UpdateCell()
> > 'use module public instead of static
> > 'static i as integer
>
> > Dim r as New ExcelReference(0,0,0,0,"Sheet1")
> > r.SetValue(i)
>
> > i = i + 1
> > if(i < 3) Then
> > MessageBox.Show(i)
> > End If
> > End Sub
>
> > ' Excel-DNA will register this as an Excel macro
> > Public Sub UpdateCellByCOM()
> > 'use module public instead of static
> > 'static i as integer
>
> > ExcelDnaUtil.Application.ActiveWorkbook.Sheets("Sheet1").Cells(1,1).value =
> > i
>
> > i = i + 1
> > if(i < 2) Then
> > MessageBox.Show(i)
> > End If
> > End Sub
>
> > End Module
> > ]]>
> > </Project>
> > </DnaLibrary>
>
> > ---------------------------------------------------------------------
> > -------------- OnTime.dna that uses OnTime --------------------------
> > ---------------------------------------------------------------------
>
> > <DnaLibrary Name="ExcelDna Test AddIn">
> > <Project Language="VB">
> > <Reference Path="System.Windows.Forms.dll"/>
> > <![CDATA[
> > Imports System.Windows.Forms
>
> > Public Module MyTestFunctions
> > Public gbRunFlag as Boolean
> > Public i as integer = 0
>
> > <ExcelCommand(MenuName:="&Timer", _
> > MenuText:="Start Timer")> _
> > Public Sub StartTimer()
> > gbRunFlag = True
>
> > 'XlCall.Excel(XlCall.xlcOnTime, DateTime.Now.AddSeconds(5),
> > "UpdateCell") 'works as well
> > 'ExcelDnaUtil.Application.OnTime(DateTime.Now.AddSeconds(5),
> > "UpdateCell")
> > ExcelDnaUtil.Application.OnTime(DateTime.Now.AddSeconds(5),
> > "UpdateCellByCOM")
> > End Sub
>
> > <ExcelCommand(MenuName:="&Timer", _
> > MenuText:="Stop Timer")> _
> > Public Sub StopTimer()
> > gbRunFlag = False
> > End Sub
>
> > ' Excel-DNA will register this as an Excel macro
> > Public Sub UpdateCell()
> > 'use module public instead of static
> > 'static i as integer
>
> > Dim r as New ExcelReference(0,0,0,0,"Sheet1")
> > r.SetValue(i)
>
> > i = i + 1
> > if(i < 2) Then
> > MessageBox.Show(i)
> > End If
>
> > 'schedule another call to itself
> > If gbRunFlag Then
> > 'XlCall.Excel(XlCall.xlcOnTime,
> > DateTime.Now.AddSeconds(5), "UpdateCell") 'works as well
>
> > ExcelDnaUtil.Application.OnTime(DateTime.Now.AddSeconds(5), "UpdateCell")
> > End If
>
> > End Sub
>
> > ' Excel-DNA will register this as an Excel macro
> > Public Sub UpdateCellByCOM()
> > 'use module public instead of static
> > 'static i as integer
>
> > ExcelDnaUtil.Application.ActiveWorkbook.Sheets("Sheet1").Cells(1,1).value =
> > i
>
> > i = i + 1
> > if(i < 2) Then
> > MessageBox.Show(i)
> > End If
>
> > 'schedule another call to itself
> > If gbRunFlag Then
> > 'XlCall.Excel(XlCall.xlcOnTime,
> > DateTime.Now.AddSeconds(5), "UpdateCellByCOM") 'works as well
>
> > ExcelDnaUtil.Application.OnTime(DateTime.Now.AddSeconds(5),
> > "UpdateCellByCOM")
> > End If
>
> > End Sub
>
> > End Module
> > ]]>
> > </Project>
> > </DnaLibrary>