Número de servicios de Windows HttpListener Memoria
-
02-10-2019 - |
Pregunta
Im un novato a las "mejores prácticas", etc de la escritura en ningún código. Tiendo a escribir una si funciona, ¿para qué arreglarlo.
Bueno, esta forma de trabajar me está aterrizando en un poco de agua caliente. Estoy escribiendo un servicio de Windows simples al servidor una sola página web. (Este servicio será incorperated a otro proyecto que supervisa los servicios y algunas carpetas en un grupo de servidores.)
Mi problema es que cada vez que una petición de que se reciba, el uso de memoria salta hacia arriba por unos pocos K por solicitud y mantiene qoing arriba en cada petición.
Ahora he encontrado que al poner GC.Collect en la mezcla que se detenga en un número determinado, pero estoy seguro de que no es destinado a ser utilizado de esta manera. Me preguntaba si me falta algo o no hacer algo que debería liberar memoria.
Este es el código:
Public Class SimpleWebService : Inherits ServiceBase
'Set the values for the different event log types.
Public Const EVENT_ERROR As Integer = 1
Public Const EVENT_WARNING As Integer = 2
Public Const EVENT_INFORMATION As Integer = 4
Public listenerThread As Thread
Dim HTTPListner As HttpListener
Dim blnKeepAlive As Boolean = True
Shared Sub Main()
Dim ServicesToRun As ServiceBase()
ServicesToRun = New ServiceBase() {New SimpleWebService()}
ServiceBase.Run(ServicesToRun)
End Sub
Protected Overrides Sub OnStart(ByVal args As String())
If Not HttpListener.IsSupported Then
CreateEventLogEntry("Windows XP SP2, Server 2003, or higher is required to " & "use the HttpListener class.")
Me.Stop()
End If
Try
listenerThread = New Thread(AddressOf ListenForConnections)
listenerThread.Start()
Catch ex As Exception
CreateEventLogEntry(ex.Message)
End Try
End Sub
Protected Overrides Sub OnStop()
blnKeepAlive = False
End Sub
Private Sub CreateEventLogEntry(ByRef strEventContent As String)
Dim sSource As String
Dim sLog As String
sSource = "Service1"
sLog = "Application"
If Not EventLog.SourceExists(sSource) Then
EventLog.CreateEventSource(sSource, sLog)
End If
Dim ELog As New EventLog(sLog, ".", sSource)
ELog.WriteEntry(strEventContent)
End Sub
Public Sub ListenForConnections()
HTTPListner = New HttpListener
HTTPListner.Prefixes.Add("http://*:1986/")
HTTPListner.Start()
Do While blnKeepAlive
Dim ctx As HttpListenerContext = HTTPListner.GetContext()
Dim HandlerThread As Thread = New Thread(AddressOf ProcessRequest)
HandlerThread.Start(ctx)
HandlerThread = Nothing
Loop
HTTPListner.Stop()
End Sub
Private Sub ProcessRequest(ByVal ctx As HttpListenerContext)
Dim sb As StringBuilder = New StringBuilder
sb.Append("<html><body><h1>Test My Service</h1>")
sb.Append("</body></html>")
Dim buffer() As Byte = Encoding.UTF8.GetBytes(sb.ToString)
ctx.Response.ContentLength64 = buffer.Length
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length)
ctx.Response.OutputStream.Close()
ctx.Response.Close()
sb = Nothing
buffer = Nothing
ctx = Nothing
'This line seems to keep the mem leak down
'System.GC.Collect()
End Sub
End Class
No dude en critisise y romper el código aparte, pero por favor bueno. He admitido yo no tienden a seguir la mejor práctica cuando se trata de la codificación.
Solución
Tiene usted razón, debe no a hacer esto. Retire la llamada Collect () y se deja correr durante una semana. Cualquier libro .NET decente hablará de cómo funciona el colector de basura y cómo lo hace no liberar inmediatamente a la memoria cuando se establece un objeto en Nothing. No se dispara hasta que ha consumido en algún lugar entre 2 y 8 megabytes. Esto no es una fuga, simplemente el uso efectivo de un recurso abundante.
Se utiliza un nuevo hilo para cada conexión individual, que es bastante caro y escalas muy mal cuando se obtiene una gran cantidad de conexiones. Considere el uso de ThreadPool.QueueUserWorkItem lugar. ThreadPool hilos son muy baratos y su asignación y ejecución está bien controlada por el administrador de subprocesos.