Timer.Stop Timer.Stop Timer.Stop Timer.Stop Method

定義

Enabledfalse に設定して、Elapsed イベントの発生を停止します。Stops raising the Elapsed event by setting Enabled to false.

public:
 void Stop();
public void Stop ();
member this.Stop : unit -> unit
Public Sub Stop ()

次の例ではSystem.Timers.Timer 、2秒 ( Timer.Elapsed 2000 ミリ秒) ごとにイベントを発生させるオブジェクトをインスタンス化し、イベントのイベントハンドラーを設定して、タイマーを開始します。The following example instantiates a System.Timers.Timer object that fires its Timer.Elapsed event every two seconds (2,000 milliseconds), sets up an event handler for the event, and starts the timer. イベントハンドラーは、発生するたびにElapsedEventArgs.SignalTimeプロパティの値を表示します。The event handler displays the value of the ElapsedEventArgs.SignalTime property each time it is raised. ユーザーが enter キーを押すと、アプリケーションはアプリケーションをStop終了する前にメソッドを呼び出します。When the user presses the Enter key, the application calls the Stop method before terminating the application.

using System;
using System.Timers;

public class Example
{
   private static System.Timers.Timer aTimer;
   
   public static void Main()
   {
      SetTimer();

      Console.WriteLine("\nPress the Enter key to exit the application...\n");
      Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
      Console.ReadLine();
      aTimer.Stop();
      aTimer.Dispose();
      
      Console.WriteLine("Terminating the application...");
   }

   private static void SetTimer()
   {
        // Create a timer with a two second interval.
        aTimer = new System.Timers.Timer(2000);
        // Hook up the Elapsed event for the timer. 
        aTimer.Elapsed += OnTimedEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
    }

    private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
                          e.SignalTime);
    }
}
// The example displays output like the following:
//       Press the Enter key to exit the application...
//
//       The application started at 09:40:29.068
//       The Elapsed event was raised at 09:40:31.084
//       The Elapsed event was raised at 09:40:33.100
//       The Elapsed event was raised at 09:40:35.100
//       The Elapsed event was raised at 09:40:37.116
//       The Elapsed event was raised at 09:40:39.116
//       The Elapsed event was raised at 09:40:41.117
//       The Elapsed event was raised at 09:40:43.132
//       The Elapsed event was raised at 09:40:45.133
//       The Elapsed event was raised at 09:40:47.148
//
//       Terminating the application...
Imports System.Timers

Public Module Example
    Private aTimer As System.Timers.Timer

    Public Sub Main()
        SetTimer()

      Console.WriteLine("{0}Press the Enter key to exit the application...{0}",
                        vbCrLf)
      Console.WriteLine("The application started at {0:HH:mm:ss.fff}",
                        DateTime.Now)
      Console.ReadLine()
      aTimer.Stop()
      aTimer.Dispose()

      Console.WriteLine("Terminating the application...")
    End Sub

    Private Sub SetTimer()
        ' Create a timer with a two second interval.
        aTimer = New System.Timers.Timer(2000)
        ' Hook up the Elapsed event for the timer. 
        AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
        aTimer.AutoReset = True
        aTimer.Enabled = True
    End Sub

    ' The event handler for the Timer.Elapsed event. 
    Private Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)
        Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
                          e.SignalTime)
    End Sub 
End Module
' The example displays output like the following:
'       Press the Enter key to exit the application...
'
'       The application started at 09:40:29.068
'       The Elapsed event was raised at 09:40:31.084
'       The Elapsed event was raised at 09:40:33.100
'       The Elapsed event was raised at 09:40:35.100
'       The Elapsed event was raised at 09:40:37.116
'       The Elapsed event was raised at 09:40:39.116
'       The Elapsed event was raised at 09:40:41.117
'       The Elapsed event was raised at 09:40:43.132
'       The Elapsed event was raised at 09:40:45.133
'       The Elapsed event was raised at 09:40:47.148
'
'       Terminating the application...

次のコード例を呼び出すスレッドを防ぐために 1 つのメソッドを示しています、Stopメソッドまで、現在の実行を続行できなくElapsedイベント終了すると、2 つの操作を防止するためにもElapsedを同じイベント ハンドラーの実行からのイベント時間 (再入とも呼ばれます)。The following code example shows one way to prevent the thread that calls the Stop method from continuing until a currently executing Elapsed event ends, and also to prevent two Elapsed events from executing the event handler at the same time (often referred to as reentrancy).

この例では、100テストの実行を実行します。The example executes 100 test runs. テストが実行されるたびに、タイマーは150ミリ秒の間隔で開始されます。Each time the test is run, the timer is started with an interval of 150 milliseconds. イベントハンドラーは、 Thread.Sleepメソッドを使用して、50 ~ 200 ミリ秒の長さでランダムに変化するタスクをシミュレートします。The event handler uses the Thread.Sleep method to simulate a task that randomly varies in length from 50 to 200 milliseconds. また、テストメソッドは、1秒間待機してからタイマーを停止する制御スレッドを開始します。The test method also starts a control thread that waits for a second and then stops the timer. コントロールスレッドがタイマーを停止したときにイベントが処理されている場合、制御スレッドはイベントが完了するまで待機してから続行する必要があります。If an event is being handled when the control thread stops the timer, the control thread must wait until the event is finished before proceeding.

メソッドInterlocked.CompareExchange(Int32, Int32, Int32)のオーバーロードは、再入を回避し、実行中のイベントが終了するまで制御スレッドが続行されないようにするために使用されます。The Interlocked.CompareExchange(Int32, Int32, Int32) method overload is used to avoid reentrancy and to prevent the control thread from continuing until an executing event ends. イベントハンドラーは、 CompareExchange(Int32, Int32, Int32)メソッドを使用して、コントロール変数を1に設定します。ただし、値が現在0の場合に限ります。The event handler uses the CompareExchange(Int32, Int32, Int32) method to set a control variable to 1, but only if the value is currently zero. これはアトミック操作です。This is an atomic operation. 戻り値が0の場合、コントロール変数が1に設定され、イベントハンドラーが処理を続行します。If the return value is zero, the control variable has been set to 1 and the event handler proceeds. 戻り値が0以外の場合は、再入を避けるために、イベントは単に破棄されます。If the return value is non-zero, the event is simply discarded to avoid reentrancy. (すべてのイベントを実行するために必要な場合、Monitorクラスは、イベントを同期するメソッドの向上になります)。イベント ハンドラーの終了時に、設定コントロール変数戻るを 0 にします。(If it were necessary to execute every event, the Monitor class would be a better way to synchronize the events.) When the event handler ends, it sets the control variable back to zero. この例では、再入によって破棄され、 Stopメソッドが呼び出された後に発生した、実行されたイベントの合計数を記録します。The example records the total number of events that executed, that were discarded because of reentrancy, and that occurred after the Stop method was called.

コントロールスレッドは、 CompareExchange(Int32, Int32, Int32)メソッドを使用して、コントロール変数を-1 (マイナス 1) に設定します。ただし、値が現在0の場合に限ります。The control thread uses the CompareExchange(Int32, Int32, Int32) method to set the control variable to -1 (minus one), but only if the value is currently zero. アトミック操作が0以外の値を返す場合、イベントは現在実行中です。If the atomic operation returns non-zero, an event is currently executing. 制御スレッドが待機して、もう一度試行します。The control thread waits and tries again. この例では、コントロールスレッドがイベントの終了を待機する必要があった回数を記録します。The example records the number of times the control thread had to wait for an event to finish.

using System;
using System.Timers;
using System.Threading;

public class Test
{    
    // Change these values to control the behavior of the program.
    private static int testRuns = 100;
    // Times are given in milliseconds:
    private static int testRunsFor = 500;
    private static int timerIntervalBase = 100;
    private static int timerIntervalDelta = 20;

    // Timers.
    private static System.Timers.Timer Timer1 = new System.Timers.Timer();
    private static System.Timers.Timer Timer2 = new System.Timers.Timer();
    private static System.Timers.Timer currentTimer = null;

    private static Random rand = new Random();

    // This is the synchronization point that prevents events
    // from running concurrently, and prevents the main thread 
    // from executing code after the Stop method until any 
    // event handlers are done executing.
    private static int syncPoint = 0;

    // Count the number of times the event handler is called,
    // is executed, is skipped, or is called after Stop.
    private static int numEvents = 0;
    private static int numExecuted = 0;
    private static int numSkipped = 0;
    private static int numLate = 0;

    // Count the number of times the thread that calls Stop
    // has to wait for an Elapsed event to finish.
    private static int numWaits = 0;

    [MTAThread]
    public static void Main()
    {
        Timer1.Elapsed += new ElapsedEventHandler(Timer1_ElapsedEventHandler);
        Timer2.Elapsed += new ElapsedEventHandler(Timer2_ElapsedEventHandler);

        Console.WriteLine();
        for(int i = 1; i <= testRuns; i++)
        {
            TestRun();
            Console.Write("\rTest {0}/{1}    ", i, testRuns);
        }

        Console.WriteLine("{0} test runs completed.", testRuns);
        Console.WriteLine("{0} events were raised.", numEvents);
        Console.WriteLine("{0} events executed.", numExecuted);
        Console.WriteLine("{0} events were skipped for concurrency.", numSkipped);
        Console.WriteLine("{0} events were skipped because they were late.", numLate);
        Console.WriteLine("Control thread waited {0} times for an event to complete.", numWaits);
    }

    public static void TestRun()
    {
        // Set syncPoint to zero before starting the test 
        // run. 
        syncPoint = 0;

        // Test runs alternate between Timer1 and Timer2, to avoid
        // race conditions between tests, or with very late events.
        if (currentTimer == Timer1)
            currentTimer = Timer2;
        else
            currentTimer = Timer1;

        currentTimer.Interval = timerIntervalBase 
            - timerIntervalDelta + rand.Next(timerIntervalDelta * 2);
        currentTimer.Enabled = true;

        // Start the control thread that shuts off the timer.
        Thread t = new Thread(ControlThreadProc);
        t.Start();

        // Wait until the control thread is done before proceeding.
        // This keeps the test runs from overlapping.
        t.Join();

    }


    private static void ControlThreadProc()
    {
        // Allow the timer to run for a period of time, and then 
        // stop it.
        Thread.Sleep(testRunsFor);
        currentTimer.Stop();

        // The 'counted' flag ensures that if this thread has
        // to wait for an event to finish, the wait only gets 
        // counted once.
        bool counted = false;

        // Ensure that if an event is currently executing,
        // no further processing is done on this thread until
        // the event handler is finished. This is accomplished
        // by using CompareExchange to place -1 in syncPoint,
        // but only if syncPoint is currently zero (specified
        // by the third parameter of CompareExchange). 
        // CompareExchange returns the original value that was
        // in syncPoint. If it was not zero, then there's an
        // event handler running, and it is necessary to try
        // again.
        while (Interlocked.CompareExchange(ref syncPoint, -1, 0) != 0)
        {
            // Give up the rest of this thread's current time
            // slice. This is a naive algorithm for yielding.
            Thread.Sleep(1);

            // Tally a wait, but don't count multiple calls to
            // Thread.Sleep.
            if (!counted)
            {
                numWaits += 1;
                counted = true;
            }
        }

        // Any processing done after this point does not conflict
        // with timer events. This is the purpose of the call to
        // CompareExchange. If the processing done here would not
        // cause a problem when run concurrently with timer events,
        // then there is no need for the extra synchronization.
    }


    // Event-handling methods for the Elapsed events of the two
    // timers.
    //
    private static void Timer1_ElapsedEventHandler(object sender, 
        ElapsedEventArgs e)
    {
        HandleElapsed(sender, e);
    }

    private static void Timer2_ElapsedEventHandler(object sender, 
        ElapsedEventArgs e)
    {
        HandleElapsed(sender, e);
    }

    private static void HandleElapsed(object sender, ElapsedEventArgs e)
    {
        numEvents += 1;

        // This example assumes that overlapping events can be
        // discarded. That is, if an Elapsed event is raised before 
        // the previous event is finished processing, the second
        // event is ignored. 
        //
        // CompareExchange is used to take control of syncPoint, 
        // and to determine whether the attempt was successful. 
        // CompareExchange attempts to put 1 into syncPoint, but
        // only if the current value of syncPoint is zero 
        // (specified by the third parameter). If another thread
        // has set syncPoint to 1, or if the control thread has
        // set syncPoint to -1, the current event is skipped. 
        // (Normally it would not be necessary to use a local 
        // variable for the return value. A local variable is 
        // used here to determine the reason the event was 
        // skipped.)
        //
        int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
        if (sync == 0)
        {
            // No other event was executing.
            // The event handler simulates an amount of work
            // lasting between 50 and 200 milliseconds, so that
            // some events will overlap.
            int delay = timerIntervalBase 
                - timerIntervalDelta / 2 + rand.Next(timerIntervalDelta);
            Thread.Sleep(delay);
            numExecuted += 1;

            // Release control of syncPoint.
            syncPoint = 0;
        }
        else
        {
            if (sync == 1) { numSkipped += 1; } else { numLate += 1; }
        }
    }
}

/* On a dual-processor computer, this code example produces
   results similar to the following:

Test 100/100    100 test runs completed.
436 events were raised.
352 events executed.
84 events were skipped for concurrency.
0 events were skipped because they were late.
Control thread waited 77 times for an event to complete.
 */
Imports System.Timers
Imports System.Threading

Public Module Test
    
    ' Change these values to control the behavior of the program.
    Private testRuns As Integer = 100 
    ' Times are given in milliseconds:
    Private testRunsFor As Integer = 500
    Private timerIntervalBase As Integer = 100
    Private timerIntervalDelta As Integer = 20

    ' Timers.
    Private WithEvents Timer1 As New System.Timers.Timer
    Private WithEvents Timer2 As New System.Timers.Timer
    Private currentTimer As System.Timers.timer

    Private rand As New Random()

    ' This is the synchronization point that prevents events
    ' from running concurrently, and prevents the main thread 
    ' from executing code after the Stop method until any 
    ' event handlers are done executing.
    Private syncPoint As Integer = 0

    ' Count the number of times the event handler is called,
    ' is executed, is skipped, or is called after Stop.
    Private numEvents As Integer = 0
    Private numExecuted As Integer = 0
    Private numSkipped As Integer = 0
    Private numLate As Integer = 0

    ' Count the number of times the thread that calls Stop
    ' has to wait for an Elapsed event to finish.
    Private numWaits As Integer = 0

    <MTAThread> _
    Sub Main()
        Console.WriteLine()
        For i As Integer = 1 To testRuns
            TestRun
            Console.Write(vbCr & "Test {0}/{1}    ", i, testRuns)
        Next

        Console.WriteLine("{0} test runs completed.", testRuns)
        Console.WriteLine("{0} events were raised.", numEvents)
        Console.WriteLine("{0} events executed.", numExecuted)
        Console.WriteLine("{0} events were skipped for concurrency.", numSkipped)
        Console.WriteLine("{0} events were skipped because they were late.", numLate)
        Console.WriteLine("Control thread waited {0} times for an event to complete.", numWaits)
    End Sub

    Sub TestRun()
        ' Set syncPoint to zero before starting the test 
        ' run. 
        syncPoint = 0

        ' Test runs alternate between Timer1 and Timer2, to avoid
        ' race conditions between tests, or with very late events.
        If currentTimer Is Timer1 Then
            currentTimer = Timer2
        Else
            currentTimer = Timer1
        End If

        currentTimer.Interval = timerIntervalBase _
            - timerIntervalDelta + rand.Next(timerIntervalDelta * 2)
        currentTimer.Enabled = True

        ' Start the control thread that shuts off the timer.
        Dim t As New Thread(AddressOf ControlThreadProc)
        t.Start()

        ' Wait until the control thread is done before proceeding.
        ' This keeps the test runs from overlapping.
        t.Join()

    End Sub


    Private Sub ControlThreadProc()
        ' Allow the timer to run for a period of time, and then 
        ' stop it.
        Thread.Sleep(testRunsFor) 
        currentTimer.Stop

        ' The 'counted' flag ensures that if this thread has
        ' to wait for an event to finish, the wait only gets 
        ' counted once.
        Dim counted As Boolean = False

        ' Ensure that if an event is currently executing,
        ' no further processing is done on this thread until
        ' the event handler is finished. This is accomplished
        ' by using CompareExchange to place -1 in syncPoint,
        ' but only if syncPoint is currently zero (specified
        ' by the third parameter of CompareExchange). 
        ' CompareExchange returns the original value that was
        ' in syncPoint. If it was not zero, then there's an
        ' event handler running, and it is necessary to try
        ' again.
        While Interlocked.CompareExchange(syncPoint, -1, 0) <> 0 
            ' Give up the rest of this thread's current time
            ' slice. This is a naive algorithm for yielding.
            Thread.Sleep(1)

            ' Tally a wait, but don't count multiple calls to
            ' Thread.Sleep.
            If Not counted Then
                numWaits += 1
                counted = True
            End If
        End While

        ' Any processing done after this point does not conflict
        ' with timer events. This is the purpose of the call to
        ' CompareExchange. If the processing done here would not
        ' cause a problem when run concurrently with timer events,
        ' then there is no need for the extra synchronization.
    End Sub


    ' Event-handling methods for the Elapsed events of the two
    ' timers.
    '
    Private Sub Timer1_ElapsedEventHandler(ByVal sender As Object, _
        ByVal e As ElapsedEventArgs) Handles Timer1.Elapsed

        HandleElapsed(sender, e)
    End Sub

    Private Sub Timer2_ElapsedEventHandler(ByVal sender As Object, _
        ByVal e As ElapsedEventArgs) Handles Timer2.Elapsed

        HandleElapsed(sender, e)
    End Sub

    Private Sub HandleElapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)

        numEvents += 1

        ' This example assumes that overlapping events can be
        ' discarded. That is, if an Elapsed event is raised before 
        ' the previous event is finished processing, the second
        ' event is ignored. 
        '
        ' CompareExchange is used to take control of syncPoint, 
        ' and to determine whether the attempt was successful. 
        ' CompareExchange attempts to put 1 into syncPoint, but
        ' only if the current value of syncPoint is zero 
        ' (specified by the third parameter). If another thread
        ' has set syncPoint to 1, or if the control thread has
        ' set syncPoint to -1, the current event is skipped. 
        ' (Normally it would not be necessary to use a local 
        ' variable for the return value. A local variable is 
        ' used here to determine the reason the event was 
        ' skipped.)
        '
        Dim sync As Integer = Interlocked.CompareExchange(syncPoint, 1, 0)
        If sync = 0 Then
            ' No other event was executing.
            ' The event handler simulates an amount of work
            ' similar to the time between events, so that
            ' some events will overlap.
            Dim delay As Integer = timerIntervalBase _
                - timerIntervalDelta / 2 + rand.Next(timerIntervalDelta)
            Thread.Sleep(delay)
            numExecuted += 1

            ' Release control of syncPoint.
            syncPoint = 0
        Else
            If sync = 1 Then numSkipped += 1 Else numLate += 1
        End If
    End Sub 

End Module

' On a dual-processor computer, this code example produces
' results similar to the following:
'
'Test 100/100    100 test runs completed.
'436 events were raised.
'352 events executed.
'84 events were skipped for concurrency.
'0 events were skipped because they were late.
'Control thread waited 77 times for an event to complete.

注釈

をにEnabled false設定して、タイミングを停止することもできます。You can also stop timing by setting Enabled to false.

注意

Elapsedイベントを発生させるシグナルは、常にThreadPoolスレッドでの実行のためにキューに入れられるので、イベント処理メソッドは、メソッドのStop呼び出しが別のスレッドで実行されるときに、1つのスレッドで実行される可能性があります。The signal to raise the Elapsed event is always queued for execution on a ThreadPool thread, so the event-handling method might run on one thread at the same time that a call to the Stop method runs on another thread. これにより、 Elapsed Stopメソッドが呼び出された後にイベントが発生する可能性があります。This might result in the Elapsed event being raised after the Stop method is called. 」セクションの2番目のコード例は、この競合状態を回避する方法の1つを示しています。The second code example in the Examples section shows one way to work around this race condition.

適用対象

こちらもご覧ください