【问题标题】:How can I get my TCP listener service to terminate correctly?如何让我的 TCP 侦听器服务正确终止?
【发布时间】:2009-12-20 03:27:25
【问题描述】:

我正在编写一个启动 TCP 侦听器的 Windows 服务。核心代码运行良好,但我在 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 上执行此操作。]

【问题讨论】:

    标签: .net vb.net windows-services visual-studio-2010


    【解决方案1】:

    您应该实现一些shutdown() 方法来优雅地关闭套接字,而不是使用Thread.Abort() 来终止线程。

    例如

    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() 方法中,您首先通过调用 myListener.Shutdown() 让 pmtListener 实例有机会正常关闭(然后设置关闭标志并关闭套接字),然后等待(最多)某个时间跨度(例如一秒)。如果线程还活着,请尝试终止它。

    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
    

    【讨论】:

    • 好吧,假设 pmtListener 有一个 shutdown() 方法。怎么称呼它?我需要重新加入生成的线程吗?
    • 给我一两秒钟的例子......我不是 VB 开发人员 ;-) 简短版本:不要使用静态方法(共享子?)而是 pmtListener 的实例(dim myListener as new pmtListener() ?) 并在其 Main() 方法上启动线程 (new Thread(AddressOf myListener.Main))
    • 该示例似乎有效(仅作为控制台应用程序测试,而不是服务)。 Socket.Accept() 调用不受 ThreadAbortException 影响的(非托管)winsock 代码。我想知道是否有办法“让它意识到”。自我提醒:那花了太长时间。多练习vb.net。它 dotnet。
    • 我仍然会这样做,但我认为从技术上讲,Join() 和 Abort() 故障安全不是必需的,因为线程是后台线程,当进程消失时应该自动终止.
    • 然后使用TCPListener的Stop()方法,msdn.microsoft.com/en-us/library/…
    猜你喜欢
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 2016-12-30
    • 2013-08-03
    • 2023-03-12
    • 2018-05-11
    • 2014-11-01
    • 2011-07-22
    相关资源
    最近更新 更多