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.

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top