我是任何代码中写作的“最佳实践”等的完全新手。 如果它有效,我倾向于只写它,为什么要修复它。
嗯,这种工作方式让我陷入了一些热水。我正在编写一个简单的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
请随意批评并撕掉代码,但请保持良好状态。我已经承认,在编码方面,我不倾向于遵循最佳实践。
答案 0 :(得分:2)
你是对的,你应该不这样做。删除Collect()调用并让它运行一周。任何体面的.NET书都会讨论垃圾收集器如何工作以及如何在将对象设置为Nothing时 not 立即释放内存。它直到你消耗了2到8兆字节之间才开始播放。这不是泄漏,只是有效利用丰富的资源。
你为每个单独的连接使用一个新线程,这非常昂贵,并且当你获得大量连接时,非常很差。请考虑使用ThreadPool.QueueUserWorkItem。 Threadpool线程非常便宜,它们的分配和执行很好地由线程池管理器控制。