F
Fred
Hello,
I am using a separate app domain to load an assembly from either disk
or cache, create an instance of it and run a method. I then call
dispose on the created instance and unload the app domain. This is
done in a web application. For some reason memory is not released and
continues to slowly but steadily grow. I tracked Working Set and
Private Bytes in Perfmon to check this.
Here is some example code:
Imports System.Reflection
Public Class CreateAppDomainLoadAssembliesCreateInstanceExecutecode
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
'NOTE: The following placeholder declaration is required by the Web
Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Dim iterations As Integer
If Not Request.Params("iterations") Is Nothing Then
If Request.Params("iterations").Length > 0 AndAlso
IsNumeric(Request.Params("iterations")) Then
iterations = CType(Request.Params("iterations"), Integer)
End If
End If
For x As Integer = 0 To iterations - 1
Response.Write((x + 1).ToString + "<br>")
CreateDomain()
Next
End Sub
Private Sub CreateDomain()
Dim DLLPath As String =
CType(ConfigurationSettings.AppSettings.Get("DLLPath"), String)
Dim FileName As String = System.IO.Path.Combine(DLLPath,
"RunTimeCompileClass.dll")
Dim CompiledState() As Byte =
HttpContext.Current.Items("CompiledState")
If CompiledState Is Nothing Then
CompiledState = LoadFileAsByteArray(FileName)
HttpContext.Current.Items("CompiledState") = CompiledState
End If
Dim ShadowCopyPath As String =
CType(ConfigurationSettings.AppSettings.Get("ShadowPathKey"), String)
Dim ShadowCopyFiles As String
Dim AppDomainApplicationName As String = "BizRuleRunner" +
Now.Ticks.ToString
Dim BSAppDomainSetup As New AppDomainSetup
Dim BSAppDomain As AppDomain
Dim NeedToLoadAssembly As Boolean = True
Dim BizRuleAssemblyName As String
Dim CurrentBizRule As RunTimeCompileBaseClass
Dim DidBizRulePass As Boolean
Dim BizRuleString As String
Dim UserRoles(0) As String
Dim MyBizRuleResult As New BizRuleResult(DidBizRulePass,
BizRuleString)
Try
If Not ShadowCopyPath Is Nothing AndAlso ShadowCopyPath <>
String.Empty AndAlso ShadowCopyPath.Length > 0 Then
ShadowCopyFiles = "true"
Else
ShadowCopyFiles = "false"
End If
BSAppDomainSetup.CachePath = ShadowCopyPath
BSAppDomainSetup.ShadowCopyFiles = ShadowCopyFiles
BSAppDomainSetup.ApplicationBase = DLLPath
BSAppDomain = AppDomain.CreateDomain(AppDomainApplicationName,
AppDomain.CurrentDomain.Evidence, BSAppDomainSetup)
BSAppDomain.SetShadowCopyPath(ShadowCopyPath)
BSAppDomain.AppendPrivatePath(AppDomain.CurrentDomain.BaseDirectory)
Dim AssemblySearch As String = "RunTimeCompileClass"
For Each CurrentAssembly As [Assembly] In BSAppDomain.GetAssemblies
' For Each CurrentAssembly As [Assembly] In
AppDomain.CurrentDomain.GetAssemblies
If CurrentAssembly.FullName.IndexOf(AssemblySearch) > -1 Then
BizRuleAssemblyName = CurrentAssembly.FullName
NeedToLoadAssembly = False
CurrentAssembly = Nothing
Exit For
End If
Next
If NeedToLoadAssembly Then
BSAppDomain.Load(CompiledState, Nothing)
'need to loop through and get the full assembly name if we had to
load it
For Each CurrentAssembly As [Assembly] In BSAppDomain.GetAssemblies
' For Each CurrentAssembly As [Assembly] In
AppDomain.CurrentDomain.GetAssemblies
If CurrentAssembly.FullName.IndexOf(AssemblySearch) > -1 Then
BizRuleAssemblyName = CurrentAssembly.FullName
CurrentAssembly = Nothing
Exit For
End If
Next
End If
CurrentBizRule =
CType(BSAppDomain.CreateInstance(BizRuleAssemblyName,
"RunTimeCompileClass").Unwrap(), RunTimeCompileBaseClass)
Dim BizruleParams As New Hashtable
UserRoles(0) = "RoleName"
BizruleParams.Add("UserRoles", UserRoles)
BizruleParams.Add("RunType", 1)
CurrentBizRule.main(BizruleParams, MyBizRuleResult)
Response.Write("Result: " + MyBizRuleResult.BizRulePassed.ToString +
"<br>")
Finally
If Not CurrentBizRule Is Nothing Then CurrentBizRule.Dispose()
If Not CompiledState Is Nothing Then CompiledState = Nothing
If Not UserRoles Is Nothing Then Array.Clear(UserRoles, 0,
UserRoles.Length)
DLLPath = Nothing
ShadowCopyPath = Nothing
ShadowCopyFiles = Nothing
AppDomainApplicationName = Nothing
AppDomain.Unload(BSAppDomain)
End Try
End Sub
Private Shared Function LoadFileAsByteArray(ByVal FileName As String)
As Byte()
Dim fs As System.IO.FileStream
Try
fs = New System.IO.FileStream(FileName, System.IO.FileMode.Open)
Dim buffer(CInt(fs.Length)) As Byte
fs.Read(buffer, 0, buffer.Length)
Return buffer
Finally
fs.Close()
End Try
Return Nothing
End Function 'loadFile
End Class
I am using a separate app domain to load an assembly from either disk
or cache, create an instance of it and run a method. I then call
dispose on the created instance and unload the app domain. This is
done in a web application. For some reason memory is not released and
continues to slowly but steadily grow. I tracked Working Set and
Private Bytes in Perfmon to check this.
Here is some example code:
Imports System.Reflection
Public Class CreateAppDomainLoadAssembliesCreateInstanceExecutecode
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
'NOTE: The following placeholder declaration is required by the Web
Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Dim iterations As Integer
If Not Request.Params("iterations") Is Nothing Then
If Request.Params("iterations").Length > 0 AndAlso
IsNumeric(Request.Params("iterations")) Then
iterations = CType(Request.Params("iterations"), Integer)
End If
End If
For x As Integer = 0 To iterations - 1
Response.Write((x + 1).ToString + "<br>")
CreateDomain()
Next
End Sub
Private Sub CreateDomain()
Dim DLLPath As String =
CType(ConfigurationSettings.AppSettings.Get("DLLPath"), String)
Dim FileName As String = System.IO.Path.Combine(DLLPath,
"RunTimeCompileClass.dll")
Dim CompiledState() As Byte =
HttpContext.Current.Items("CompiledState")
If CompiledState Is Nothing Then
CompiledState = LoadFileAsByteArray(FileName)
HttpContext.Current.Items("CompiledState") = CompiledState
End If
Dim ShadowCopyPath As String =
CType(ConfigurationSettings.AppSettings.Get("ShadowPathKey"), String)
Dim ShadowCopyFiles As String
Dim AppDomainApplicationName As String = "BizRuleRunner" +
Now.Ticks.ToString
Dim BSAppDomainSetup As New AppDomainSetup
Dim BSAppDomain As AppDomain
Dim NeedToLoadAssembly As Boolean = True
Dim BizRuleAssemblyName As String
Dim CurrentBizRule As RunTimeCompileBaseClass
Dim DidBizRulePass As Boolean
Dim BizRuleString As String
Dim UserRoles(0) As String
Dim MyBizRuleResult As New BizRuleResult(DidBizRulePass,
BizRuleString)
Try
If Not ShadowCopyPath Is Nothing AndAlso ShadowCopyPath <>
String.Empty AndAlso ShadowCopyPath.Length > 0 Then
ShadowCopyFiles = "true"
Else
ShadowCopyFiles = "false"
End If
BSAppDomainSetup.CachePath = ShadowCopyPath
BSAppDomainSetup.ShadowCopyFiles = ShadowCopyFiles
BSAppDomainSetup.ApplicationBase = DLLPath
BSAppDomain = AppDomain.CreateDomain(AppDomainApplicationName,
AppDomain.CurrentDomain.Evidence, BSAppDomainSetup)
BSAppDomain.SetShadowCopyPath(ShadowCopyPath)
BSAppDomain.AppendPrivatePath(AppDomain.CurrentDomain.BaseDirectory)
Dim AssemblySearch As String = "RunTimeCompileClass"
For Each CurrentAssembly As [Assembly] In BSAppDomain.GetAssemblies
' For Each CurrentAssembly As [Assembly] In
AppDomain.CurrentDomain.GetAssemblies
If CurrentAssembly.FullName.IndexOf(AssemblySearch) > -1 Then
BizRuleAssemblyName = CurrentAssembly.FullName
NeedToLoadAssembly = False
CurrentAssembly = Nothing
Exit For
End If
Next
If NeedToLoadAssembly Then
BSAppDomain.Load(CompiledState, Nothing)
'need to loop through and get the full assembly name if we had to
load it
For Each CurrentAssembly As [Assembly] In BSAppDomain.GetAssemblies
' For Each CurrentAssembly As [Assembly] In
AppDomain.CurrentDomain.GetAssemblies
If CurrentAssembly.FullName.IndexOf(AssemblySearch) > -1 Then
BizRuleAssemblyName = CurrentAssembly.FullName
CurrentAssembly = Nothing
Exit For
End If
Next
End If
CurrentBizRule =
CType(BSAppDomain.CreateInstance(BizRuleAssemblyName,
"RunTimeCompileClass").Unwrap(), RunTimeCompileBaseClass)
Dim BizruleParams As New Hashtable
UserRoles(0) = "RoleName"
BizruleParams.Add("UserRoles", UserRoles)
BizruleParams.Add("RunType", 1)
CurrentBizRule.main(BizruleParams, MyBizRuleResult)
Response.Write("Result: " + MyBizRuleResult.BizRulePassed.ToString +
"<br>")
Finally
If Not CurrentBizRule Is Nothing Then CurrentBizRule.Dispose()
If Not CompiledState Is Nothing Then CompiledState = Nothing
If Not UserRoles Is Nothing Then Array.Clear(UserRoles, 0,
UserRoles.Length)
DLLPath = Nothing
ShadowCopyPath = Nothing
ShadowCopyFiles = Nothing
AppDomainApplicationName = Nothing
AppDomain.Unload(BSAppDomain)
End Try
End Sub
Private Shared Function LoadFileAsByteArray(ByVal FileName As String)
As Byte()
Dim fs As System.IO.FileStream
Try
fs = New System.IO.FileStream(FileName, System.IO.FileMode.Open)
Dim buffer(CInt(fs.Length)) As Byte
fs.Read(buffer, 0, buffer.Length)
Return buffer
Finally
fs.Close()
End Try
Return Nothing
End Function 'loadFile
End Class