VB .Net服务在线程休眠时不会停止

问题描述:

我有一个VB .Net服务,它使用System.Threading而不是定时器来基本上做一个定时器应该做的事情。我的问题是在线程处于睡眠状态时停止服务。请参见下面的代码:服务启动VB .Net服务在线程休眠时不会停止

如果例如1分钟后
Imports System.Threading 

Public Class AService 
    Private stopping As Boolean 
    Private stoppedEvent As ManualResetEvent 

    Public Sub New() 
     InitializeComponent() 
     Me.stopping = False 
     Me.stoppedEvent = New ManualResetEvent(False) 
    End Sub 

    Protected Overrides Sub OnStart(ByVal args() As String) 
     ' Add code here to start your service. This method should set things 
     ' in motion so your service can do its work. 
    End Sub 

    Protected Overrides Sub OnStop() 
     ' Add code here to perform any tear-down necessary to stop your service. 
     Me.stopping = True 
     Me.stoppedEvent.WaitOne() 
    End Sub 

    Private Sub ServiceWorkerThread(ByVal state As Object) 
     ' Periodically check if the service is stopping. 
     Do While Not Me.stopping 
      ' Perform main service function here... 
      ' do anything here and wait 15 minutes before doing it again 
      Thread.Sleep(15 * 60000) ' Sleep for interval 
     Loop 

     ' Signal the stopped event. 
     Me.stoppedEvent.Set() 
    End Sub 
End Class 

,就不能停止,直到它每隔15分钟蜱和线程被唤醒。有什么方法可以捕捉服务试图停止的信号,并中断线程?

这是我使用的代码。在睡觉或表演时停止没有问题。

Class MyService 
    Inherits ServiceBase 

    Private Shared ReadOnly SleepPeriod As New TimeSpan(0, 15, 0) 
    Private Shared ReadOnly StopTimeout As New TimeSpan(0, 3, 0) 
    Private _TerminationHandle As New ManualResetEvent(False) 
    Private _IsRunning As Boolean = False 
    Private _ServiceThread As New Thread(Addressof ServiceMain) 

    Protected Overrides Sub OnStart(args As String()) 
     _TerminationHandle.Reset() 
     _IsRunning = True 
     _ServiceThread.Start() 
    End Sub 

    Protected Overrides Sub OnStop() 
     _TerminationHandle.Set() 
     _IsRunning = False 
     ' Terminate the thread if it doesn't stop within 3 minutes of request. 
     If Not _ServiceThread.Join(StopTimeout) Then _ServiceThread.Abort() 
     _TerminationHandle.Close() ' Can use .Dispose() if using .Net 4.0 or later. 
    End Sub 

    Private Sub ServiceMain() 
     Do 
      ' TODO: Do work here. Watch for "_IsRunning = False" to abort working when stopping. 

      ' Sleep for 15 minutes at a time. Terminate when service is stopping. 
     Loop While _IsRunning AndAlso TerminationHandle.WaitOne(SleepPeriod) 
     ' TODO: Clean up. 
    End Sub 
End Class 
+0

由于其保护级别,_TerminationHandle.Dispose()不可访问。有任何想法吗?这是完美的解决方案 – 2012-02-14 15:55:37

+0

我正在使用.Net 3.5,切换到4.0,现在它的工作。我必须做一些测试,但是谢谢,这是一个很好的代码库 – 2012-02-14 16:06:21

+0

啊,我不知道这是最近的一次增加。你可以在早期版本的.Net中使用'.Close()'。我在答案中做了一个笔记。谢谢! – 2012-02-14 21:58:43

在您当前的型号中,没有。您只使用单个线程,并且您的代码在15分钟内显式“暂停”该线程,因此在此期间任何事件都没有响应。但是,如果您对此采取稍微改进的方法,则可以改进:在不同线程中运行您的ServiceWorkerThread,然后您的主线程可以保持对外部事件的响应。当“停止”信号到达时,如果需要,您可以强制中止工作线程。

+0

约是怎么回事很好的解释,给这个使用http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx – Gent 2012-02-14 22:18:27

看看在Thread.Interrupt方法:http://msdn.microsoft.com/en-us/library/system.threading.thread.interrupt.aspx#Y0

然而,这需要你有机会到正在运行的的Thread实例“的服务。”如果这是主线程,那么这是一个不行,但如果它是一个产生的线程,那么你可以调用中断,它会中断处于休眠/阻塞状态的Thread

+0

一试这是主线程 – 2012-02-13 21:26:07

+0

如果您不能将代码移动到单独的线程中,那么除了执行一些反模式忙碌等待外,没有办法绕过它。您可以通过实施类似于rerun的解决方案来最大限度地减少关闭“滞后”,并将睡眠时间设置为更可接受的(几秒钟或更多沿着这些线)。 – Kiril 2012-02-13 21:31:03