Как я могу заставить службу прослушивателя TCP корректно завершить работу?
-
20-09-2019 - |
Вопрос
Я пишу службу Windows, которая запускает прослушиватель TCP.Основной код работает нормально, но у меня возникли проблемы с механикой службы Windows.
Прямо сейчас, когда моя служба запускается, она создает поток и запускает в нем прослушиватель TCP.Затем, когда служба останавливается, она завершает этот поток:
Public Class txnSocketService
Inherits System.ServiceProcess.ServiceBase
Private listenerThread As Thread
Public Sub New()
Me.ServiceName = "txnSocketService"
Me.CanStop = True
Me.CanPauseAndContinue = True
Me.AutoLog = True
End Sub
Shared Sub Main()
System.ServiceProcess.ServiceBase.Run(New txnSocketService)
End Sub
Protected Overrides Sub OnStart(ByVal args() As String)
listenerThread = New Thread(AddressOf pmtListener.Main)
listenerThread.IsBackground = True
listenerThread.Start()
End Sub
Protected Overrides Sub OnStop()
listenerThread.Abort()
End Sub
Private Sub InitializeComponent()
'
'txnSocketService
'
Me.ServiceName = "txnSocketService"
End Sub
End Class
Запуск работает нормально.Однако если я остановлю службу, процесс службы не завершится.Что я делаю не так?
[Кстати, сейчас я делаю это на VS2010 Beta 2, если это имеет значение.]
Решение
Вместо завершения потока с помощью Thread.Abort() вам следует реализовать некоторый метод Shutdown(), который корректно закрывает сокет.
например
Public Class pmtListener
Protected shutingdown As Boolean = False
' [...] '
Public Sub Shutdown()
shutingdown = True
socketListen.Close()
End Sub
Sub Main()
Dim socketAccepted As Socket
shutingdown = False
socketListen.Listen(3)
While Not shutingdown
Try
socketAccepted = socketListen.Accept()
' do something with socketAccepted '
socketAccepted.Close()
socketAccepted = Nothing
Catch ex As SocketException
If shutingdown Then
' ignoring it '
End If
End Try
End While
End Sub
Когда Shutdown() вызывает метод socketListen.Close(), а рабочий поток в данный момент ожидает нового соединения, будет вызвано SocketExcpetion.Мы просто игнорируем это.
В вашем методе OnStop() вы сначала даете экземпляру pmtListener возможность корректно завершить работу, вызывая myListener.Shutdown() (который затем устанавливает флаг выключения и закрывает сокет), а затем ждете (до) определенного периода времени (например,одна секунда).Если поток все еще жив, попробуйте завершить его.
Public Class txnSocketService
Inherits System.ServiceProcess.ServiceBase
Protected myListener as pmtListern
Protected listenerThread As Thread
' [...] '
Protected Overrides Sub OnStart(ByVal args() As String)
myListener = new pmtListener
listenerThread = New Thread(AddressOf myListener.Main)
listenerThread.IsBackground = True
listenerThread.Start()
End Sub
Protected Overrides Sub OnStop()
myListener.Shutdown()
listenerThread.Join(1000) ' give it a second '
If listenerThread.IsAlive Then
listenerThread.Abort()
End If
End Sub