Windows服务HTTPListener内存问题

Windows服务HTTPListener内存问题,windows,vb.net,memory,service,httplistener,Windows,Vb.net,Memory,Service,Httplistener,我对任何代码的“最佳实践”等都是一个完全的新手。 我倾向于写一封信,如果它有效,为什么要修复它 嗯,这种工作方式让我陷入困境。我正在编写一个简单的windows服务来服务一个网页。(此服务将被导入到另一个项目中,该项目将监视一组服务器上的服务和一些文件夹。) 我的问题是,每当接收到一个请求时,每个请求的内存使用量都会增加几K,并且每个请求的内存使用量都会不断增加 现在我发现,通过将GC.Collect放在混合物中,它会在某个特定的数字处停止,但我确信它不应该这样使用。我想知道我是否错过了什么或者

我对任何代码的“最佳实践”等都是一个完全的新手。 我倾向于写一封信,如果它有效,为什么要修复它

嗯,这种工作方式让我陷入困境。我正在编写一个简单的windows服务来服务一个网页。(此服务将被导入到另一个项目中,该项目将监视一组服务器上的服务和一些文件夹。)

我的问题是,每当接收到一个请求时,每个请求的内存使用量都会增加几K,并且每个请求的内存使用量都会不断增加

现在我发现,通过将GC.Collect放在混合物中,它会在某个特定的数字处停止,但我确信它不应该这样使用。我想知道我是否错过了什么或者没有做一些我应该做的事情来释放记忆

代码如下:

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
公共类SimpleWebService:继承ServiceBase
'设置不同事件日志类型的值。
Public Const EVENT_错误为整数=1
Public Const EVENT_警告为整数=2
Public Const EVENT_信息为整数=4
公共listenerThread作为线程
将HTTPListner设置为HttpListener
Dim blnKeepAlive为布尔值=真
共享子主目录()
作为ServiceBase()的Dim ServicesToRun
ServicesToRun=New ServiceBase(){New SimpleWebService()}
ServiceBase.Run(ServicesToRun)
端接头
受保护的重写子启动(ByVal args作为字符串())
如果未支持HttpListener.IsSupported,则
CreateEventLogEntry(“需要Windows XP SP2、Server 2003或更高版本才能“&”使用HttpListener类。”)
我停下来
如果结束
尝试
listenerThread=新线程(ListenForConnections的地址)
listenerThread.Start()
特例
CreateEventLogEntry(例如消息)
结束尝试
端接头
受保护的覆盖子桌面()
blnKeepAlive=False
端接头
私有子CreateEventLogEntry(ByRef StreeventContent作为字符串)
作为字符串的Dim sSource
像绳子一样沉重
sSource=“Service1”
sLog=“应用程序”
如果不存在EventLog.SourceExists(sSource),则
CreateEventSource(sSource,sLog)
如果结束
将ELog变为新事件日志(sLog,“.”,sSource)
文字记录(strEventContent)
端接头
公共子列表信息连接()
HTTPListner=新的HttpListener
HTTPListner.Prefixes.Add(“http://*:1986/”)
HTTPListner.Start()
趁Blnkeepa活着的时候做
将ctx设置为HttpListenerContext=HTTPListner.GetContext()
Dim HandlerThread As Thread=新线程(ProcessRequest的地址)
HandlerThread.Start(ctx)
HandlerThread=无
环
HTTPListner.Stop()
端接头
私有子进程请求(ByVal ctx作为HttpListenerContext)
将某人调整为StringBuilder=新StringBuilder
某人附加(“测试我的服务”)
某人加上(“”)
Dim buffer()为Byte=Encoding.UTF8.GetBytes(sb.ToString)
ctx.Response.ContentLength64=缓冲区.Length
ctx.Response.OutputStream.Write(缓冲区,0,缓冲区.长度)
ctx.Response.OutputStream.Close()
ctx.Response.Close()
没什么
缓冲区=无
ctx=无
“这条线路似乎可以减少内存泄漏
'System.GC.Collect()
端接头
末级
请随意批评和撕毁代码,但请友好。我承认,在编码方面,我不倾向于遵循最佳实践。

你是对的,你不应该这样做。删除Collect()调用并让它运行一周。任何一本像样的.NET书籍都会讨论垃圾收集器是如何工作的,以及当您将一个对象设置为“无”时,它是如何不立即释放内存的。直到你消耗了2到8兆字节,它才会启动。这不是一个漏洞,只是对丰富资源的有效利用

每个单独的连接都使用一个新线程,这非常昂贵,并且在连接很多时扩展性非常差。请考虑使用TyeRePoL.QueLeUrWorkItor。线程池线程非常便宜,它们的分配和执行由线程池管理器很好地控制