Code in finalize causes session to end!

R

Rob

This is a weird one... I've got a class called PageInfo that has the
following finalize code:

Protected Overrides Sub Finalize()
MyBase.Finalize()
Do While m_TempFolders.Count
Dim TempPath As String = m_TempFolders.Dequeue
Granite.DeleteFolder(TempPath)
Loop
End Sub

The Granite.DeleteFolder routine is show belown. Basically, the class uses
some temporary folders. When the class creates them, it sticks the path in
the m_TempFolders queue. When the class is destroyed by the garbage
collector, the Finalize routine is called and deletes the temporary folder.
The way the program works is that upto ten PageInfo objects are kept in a
stack and when the 10th one is added, the one out of the other end of the
stack is deleted. This causes the finalize routine to be called shortly
afterwards.

The temporary folder is getting deleted okay BUT the session terminates -
the ASP.NET v2 Session_End event first, followed shortly by the
Session_Start.

Is it legal to call code like in DeleteFolder from within Finalize?

Thanks, Rob.

' DeleteFolder: Removes a folder and *all* the contents. USE WITH CARE!!

Public Sub DeleteFolder(ByVal Path As String)
If System.IO.Directory.Exists(Path) Then
For Each File As String In System.IO.Directory.GetFiles(Path)
Try
System.IO.File.SetAttributes(File,
IO.FileAttributes.Normal)
System.IO.File.Delete(File)
Catch ex As Exception
' Ignore delete error
End Try
Next
For Each Directory As String In
System.IO.Directory.GetDirectories(Path)
DeleteFolder(Directory)
Next
Try
System.IO.Directory.Delete(Path)
Catch ex As Exception
' Ignore delete folder error
End Try
End If
End Sub
 
R

Rob

Protected Overrides Sub Finalize()
MyBase.Finalize()
Do While m_TempFolders.Count
Dim TempPath As String = m_TempFolders.Dequeue
Granite.DeleteFolder(TempPath)
Loop
End Sub

PS. If I comment out the Granite.DeleteFolder call, then the problem doesn't
occur - except of course the temp folder isn't deleted.

Rob.
 
C

Cor Ligthert[MVP]

Rob,

Why are you using the finalize method to do normal things. It is advices to
avoid the finalize as hell to let the managed code to work properly. Don't
this not give problems?

Cor
 
R

Rob

Why are you using the finalize method to do normal things. It is advices
to avoid the finalize as hell to let the managed code to work properly.
Don't this not give problems?

The Finalize() method is the only way to ensure that the resources
(temporary folders) in this case are cleaned up. These PageInfo objects hold
(on the server) information about pages a user has previously visited. The
user could at any time go back to these pages. There could equally just
close the browser window. The application has no idea this has happened.
Therefore, the normal "cleanup" trigger in a Windows program doesn't occur.
All you get is the session ending (say) 20 minutes later.

I suppose I could change the code to delete the folders in the Session_End()
event but that kinds of annoys as the cleanup of the resources doesn't
belong with the objects it's associated with anymore.

The question as to why deleting folders and files from Finalize() causes a
new session is still confusing though. I did read somewhere that the
Finalize() method may be called from a different thread to the rest of the
application which may be important...

Cheers, Rob.
 
P

Patrice

Folders are monitored by the ASP.NET application so if you change a folder
beneath your web application you might cause an application restart (if 2.0
you can use health monitoring to easily track those restarts).

My personal preference would be to put my temp files outside of my web site.
 
M

Mach58

This is a weird one... I've got a class called PageInfo that has the
following finalize code:

Protected Overrides Sub Finalize()
MyBase.Finalize()
Do While m_TempFolders.Count
Dim TempPath As String = m_TempFolders.Dequeue
Granite.DeleteFolder(TempPath)
Loop
End Sub

The Granite.DeleteFolder routine is show belown. Basically, the class uses
some temporary folders. When the class creates them, it sticks the path in
the m_TempFolders queue. When the class is destroyed by the garbage
collector, the Finalize routine is called and deletes the temporary folder.
The way the program works is that upto ten PageInfo objects are kept in a
stack and when the 10th one is added, the one out of the other end of the
stack is deleted. This causes the finalize routine to be called shortly
afterwards.

The temporary folder is getting deleted okay BUT the session terminates -
the ASP.NET v2 Session_End event first, followed shortly by the
Session_Start.

Is it legal to call code like in DeleteFolder from within Finalize?

Why not implement IDisposable, and call yourObject.Dispose() when you
reach 10 items?

Finalizers should only be used for when *directly* handling unmanaged
resources, which you are not doing here. (Unmanaged = IntPtr,
usually; managed = FileStream, etc)

Mach
 
R

Rob

Folders are monitored by the ASP.NET application so if you change a folder
beneath your web application you might cause an application restart (if
2.0 you can use health monitoring to easily track those restarts).

Ahh - that might explain a lot... I can probably record it to not use a
temporary folder at all and simply put the files in a single flat temp
folder.
My personal preference would be to put my temp files outside of my web
site.

The temp folders contain temporary HTML files that have to within the
website as they are served up to the browser. The particular application is
a pubs database where there are guide entries per pub. The user can be
working on a pub entry and request to display how the guide entry will look.
This requires a temporary HTML and JPG to be generated, displayed and then
thrown away.

Cheers, Rob.
 
R

Rob

Why not implement IDisposable, and call yourObject.Dispose() when you
reach 10 items?

Because I kind of like not having to worry about cleanup in VB.NET if you
see what I mean. I maintain a large VB6 application and making sure that we
cleanup resources manually is one of the biggest headaches of the entire
system.

I assumed that unless you were worried about scarse resources then relying
upon the garbage collector was "good practise" and that IDispose should be
used for those cases where you want to instantly free up resources and not
depending upon the garbage collector doing it at some undermined point in
the future.

The problem I see with IDispose is that it has to be called manually by the
using code which is IMHO no better than having to implement memory cleanup
in C++ destructors.

Finalize is attractive in that you know that it's going to be called
*automatically* by the garbage collector at some point so you don't have to
worry about manually calling the dispose method.
Finalizers should only be used for when *directly* handling unmanaged
resources, which you are not doing here. (Unmanaged = IntPtr,
usually; managed = FileStream, etc)

Can you make temporary files managed?

Actually, I'm tempted to maintain a list of temporary files to be deleted in
the session state and delete them in one go when the session ends.

I suspect the other post about the application restarting when folders
change in a website is probably the cause.

Cheers, Rob.
 
R

Rob

Folders are monitored by the ASP.NET application so if you change a folder
beneath your web application you might cause an application restart (if
2.0 you can use health monitoring to easily track those restarts).

You are exactly spot on here!! I happened to have a break point in
Session_End and manually deleted a folder in the ~/Temp/ folder and bang -
it fired.

I've recoded the temporary files to just use files and not folders.

Cheers, Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top