خدمة Windows Service Httplistener مشكلة
-
02-10-2019 - |
سؤال
أنا مبتدئ كامل لـ "أفضل الممارسات" وما إلى ذلك في أي رمز. أميل إلى كتابته إذا كان يعمل ، فلماذا إصلاحه.
حسنًا ، هذه الطريقة في العمل هي التي تهبطني في بعض الماء الساخن. أنا أكتب خدمة 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
لا تتردد في النقد وتمزيق الكود ولكن يرجى أن تكون لطيفًا. لقد اعترفت أنني لا أميل إلى اتباع أفضل الممارسات عندما يتعلق الأمر بالترميز.
المحلول
أنت على حق ، يجب عليك ليس أن تفعل هذا. قم بإزالة مكالمة Collect () واتركها تعمل لمدة أسبوع. سيتحدث أي كتاب .NET لائق عن كيفية عمل جامع القمامة وكيف يعمل ليس حرر الذاكرة فورًا عند تعيين كائن على لا شيء. لا يتم تشغيله حتى تستهلك مكانًا ما بين 2 و 8 ميغابايت. هذا ليس تسربًا ، وهو مجرد استخدام فعال لمورد وفيرة.
يمكنك استخدام موضوع جديد لكل اتصال فردي ، وهذا مكلف للغاية ومقاييس جداً سيئ عندما تحصل على الكثير من الاتصالات. النظر في استخدام threadpool.queueUserworkItem بدلا من ذلك. المواضيع Threadpool رخيصة للغاية وتخصيصها وتنفيذها يتم التحكم فيها بشكل جيد من قبل مدير ThreadPool.