Best Practices for Web Apps, with regard to Memory Leaks and house keeping?

Hello all.

I noticed that my web app is increasing its memory usage, and not giving it back either when a page is closed, or the Session is ended.
When the user logs out, this code is executed:

UserName = ""
LoggedIn = False
//ShowURL("http://www.Axcys.com ")

If Self.PageCount > 0 Then 
  For i As Integer = 0 To Self.PageCount -1 
    If Self.PageAtIndex(i).Name <> CurrentPage.Name Then
      Self.PageAtIndex(i).Close
    End If
  Next i
End If
CurrentPage.Close
ShowURL("http://www.Axcys.com ")

I have a terrible feeling tho, that I am not performing correct cleanup work myself. For example, when and what objects are necessary to set to Nil in code? When does a RemoveHandler method have to be used?

Can anyone point me to a specific document that provides a list of all of the items that I need to clean up/destroy either when closing a page, or the entire session? Searching through the forum, there are LOTS of posts on the subject. Some new, some old, but none really complete, and none that appear to cover the subject with regard to the Web App framework of today. I would hate to waste time and effort, or make my matter worse by using outdated methods.

All aid is appreciated!
Thanks all,
Tim

Ok, first of all, what you are doing there with closing all of the pages is overkill. When a session dies (about 3 minutes after a user leaves your app*) it will go through and attempt to release things like this for you.

That said (and the reason for the *), if you’ve created any situations which cause things to not be able to release, none of this will work anyway.

The usual suspect for this is circular references when class A holds a reference to class B and B to A. Or even worse, a class holds a reference to itself. AddHandler is great at silently doing this to you.

Lets take an httpsocket for example. Because they’re not Session aware, people tend to do two things…
A. Create a property somewhere in a WebPage to hold onto the socket so it doesn’t go out of scope.
B. Create one or more AddHandler calls which point back to the WebPage.

When cleaning up, the reference counting system will never reach zero for these two items. If they don’t reach zero, their destructors don’t fire and they’re not released from memory. Subsequently the Session itself doesn’t get destroyed either because one of its children is still there.

Same goes for just keeping references in both directions. WebSessions must keep track of their pages. But I see quite often people putting hard references to the session on their WebPages ( or children thereof ).

So yes, if you use AddHandler, you must use RemoveHandler later to sever that line link.

You should not be relying on users “logging out” to do your cleanup work, because many users will just leave the app and assume it’s done for them.

If you make any circular references, you must disconnect at least one reference to allow them to clean up.

Thanks for your detailed reply Greg.

In my case, all pages are set to Implicit Instancing -OFF. The Session has a Property for each page, where it is created - so the session owns it, normally only 1 page at a time is opened.

On Page Menu:

Session.ShowReportConfigPage

In Session - the page is a property of Session:

Dim FoundOne As Boolean 

If Self.PageCount > 0 Then 
  For i As integer = 0 to Self.PageCount -1 
    If Self.PageAtIndex(i).Name = "ReportMgmntPage" Then FoundOne = True
  Next i
End If


If FoundOne = False Then 
  frmReportMgmntPage = New ReportMgmntPage
  frmReportMgmntPage.Show
  
  For i As integer = 0 to Self.PageCount -1 
    If Self.PageAtIndex(i).Name <> "ReportMgmntPage" Then 
      Dim n As String = Self.PageAtIndex(i).Name
      Self.PageAtIndex(i).Close
    end If
  Next i
  
Else
  For i As integer = 0 to Self.PageCount -1 
    If Self.PageAtIndex(i).Name <> "ReportMgmntPage" Then 
      Dim n As String = Self.PageAtIndex(i).Name
      Self.PageAtIndex(i).Close
    end If
  Next i
  frmReportMgmntPage.Visible = True
End If
Return

If there were a reference back to the Session, it would be to the database - Sesson.db.xxx, since the Session has opened the database and holds all references to it; OR to a property of the Session. But since the Session owns the Page, would that remove the circular reference problem?

Another possible problem may be how I am using IPS sockets. I have one instantiated in the App. This communicates with each Session bi-directionally. There are no instances of it in any object other than the App, but data is sent to it from the Session.Page to Session to App. And the other way around. Is this a problem? The idea behind this was to have a single connection to another running app. App pages need the same info sent to it (from the other app), but not all will send anything, or even something, to the other running app - so it is mostly one way communication (Other app -> Web app).

I also use dialogs. Do they need to be destroyed programmatically after each use, or when done with the page?

Same with Containers. Some are placed on the page at design time, some are instantiated as a property of the page, and then EmbedWithin the page then AddHandler is used.

In the last case, where AddHandler is used, they need to be explicitly Removed during the pages close event - correct?

However, if the Container objects do NOT use AddHandler, then there is no destruction I need to do correct?

In a pages Open Event

cntGridMstr2 = New cntGridMaster  //No addHandler, but the cntGridMaster is a container object, property cntGridMstr2 is private to the page
 mnuNavMain = New Navigator_Main    //mnuNaveMain is a page property, Navigator_Main is a series of Container objects
mnuNavMain.Top = 0
mnuNavMain.Width = Self.Width
mnuNavMain.EmbedWithin(Self, 0, 0, mnuNavMain.Width, mnuNavMain.Height)

AddHandler mnuNavMain.evnt_ShowMenu, AddressOf ShowMenu
AddHandler mnuNavMain.evnt_ShowGate, AddressOf ShowGate

Any problems with what you see above, other than missing the RemoveHandler code?

Thank you again!
Tim