2012-02-13 3 views
1

私はVBの.Netサービスを持っています。これは、基本的にタイマーが行うべきことをタイマーの代わりにSystem.Threadingを使用しています。私の問題は、スレッドがスリープ状態にある間にサービスを停止することです。スレッドがスリープしている間に.Netサービスが停止しない

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 

サービスが開始されてから1分後には、15分間隔のティックとスレッドが起動するまで停止できません。サービスが停止しようとしている信号をキャッチしてスレッドを中断する方法はありますか?

答えて

1

私が使用するコードは次のとおりです。それは睡眠中または実行中に停止する問題はありません。

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()にアクセスできません。何か案は?これは完璧な解決策です。 –

+0

.Net 3.5を使用していましたが、4.0に切り替えました。私はいくつかのテストを行う必要がありますが、ありがとう、これは素晴らしいコードベースです –

+0

ああ、私はそれが最近追加されたことを知らなかった。以前のバージョンの.Netでは '.Close()'を代わりに使うことができます。私は答えを書き留めました。ありがとう! –

1

現在のモデルでは、いいえ。 1つのスレッドしか使用しておらず、あなたのコードはスレッドを明示的に「一時停止」しているため、その間に発生したイベントに対しては応答しません。 サブを別のスレッドで実行すると、外部スレッドに応答してメインスレッドが応答したままになる可能性があります。 「停止」信号が到着したら、必要に応じてワーカースレッドを強制的に中止することができます。

+0

良い説明、それはメインスレッドでhttp://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx – Gent

0

Thread.Interrupt方法を見てみましょう:http://msdn.microsoft.com/en-us/library/system.threading.thread.interrupt.aspx#Y0

をしかし、これはあなたが実行されているThreadインスタンスにアクセスされている必要があり、「サービス」をそれがメインスレッドなら、それは無駄ですが、それが発生したスレッドであれば割り込みを呼び出すことができ、スリープ/ブロッキング状態にあるThreadを中断します。

+0

を使用して、この試みを与えます –

+0

コードを別のスレッドに移動できない場合、いくつかのパターンのビジー待機を除いて、その周囲には方法がありません。再実行と同様のソリューションを実装することで、シャットダウンの「遅れ」を最小限に抑えることができます。また、スリープ時間をより受け入れやすいものに設定するだけです。 – Kiril

関連する問題