2011-04-14 2 views
1

나는 그렇게처럼 내 초기화() 메소드에서 간단한 System.Timers.Timer을 만들어 :적절한 방법은

초기화()

 dataUpdateTimer = new Timer(DATA_POLLING_TIME); 
     dataUpdateTimer.Elapsed += new ElapsedEventHandler(UpdateTimer_Elapsed); 
     dataUpdateTimer.Enabled = true; 

를 내가 제대로 초기화 해제하고 싶습니다. 어떻게해야합니까?

UNINIT()를

 if (null != dataUpdateTimer) 
     { 
      dataUpdateTimer.Close(); 
      dataUpdateTimer.Enabled = false; 
     } 

내가 핸들러를 제거해야합니까 : 다음은 내가 가지고 있지만 때로는 핸들러 메소드 unitialization 후라고 무엇인가?

감사합니다.

+0

다시 사용 하시겠습니까? –

+0

Close() 및 Enabled = false를 모두 수행 할 필요가 없습니다. – manojlds

+0

@Steve 아니요, 끝났습니다. –

답변

2

내가 플래그를 설정하여 해당 플래그가 설정되어 있으면 더 이상 처리하지 않도록 처리기가 밀리 초 단위로 호출되지 않는다고 보장 할 수 없다고 생각합니다. . 그러나 Timer가 이미 처리 중이면 다음 반복까지 계속됩니다.

이벤트 처리 방법은 다른 스레드가 정지 방법 를 호출하거나 Enabled 속성을 false로 설정하는 동시에 하나의 스레드에서 실행할 수 있습니다 MSDN에

는,이 말을 가지고 . 타이머가 이 중지 된 후 Elapsed 이벤트 이 발생합니다. Stop 메서드에 대한 예제 코드는이 경쟁 조건을 피하는 한 가지 방법을 보여줍니다. 은 MSDN 페이지에서

Stop에 :

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. 
*/ 
+0

견고한 솔루션 @ 0A0D에 감사드립니다. 그러나 Mark L.의 솔루션은 더 간단하고 동일한 작업을 수행합니다. –

+0

@ 라이언, 그렇지 않습니다. 핸들러를 시작할 때의 시간 비교는 아무 것도 보장하지 않습니다. 타이머를 중지하는 동안 핸들러가 이미 실행 중일 수 있습니다. – Rotsor

+0

정확합니다. 그러나 비록 핸들러가 호출 되더라도 핸들러 내부의 코드가 실행되지 않는 한 내 목적으로는 충분하다고 생각합니다. –

0

핸들러는 타이머가 비활성화 된 후에도 호출하는 것이 가능하다 System.Timers.Timer에 대한 MS의 문서에 따르면. 거기에서 그들은 종료 된 시간을 기록하고 핸들러의 시작 부분에서 ElapsedEventArgs.SignalTime과 그 시간을 비교하여 핸들러 코드가 실행되지 않도록하는 것이 좋습니다.

+0

귀하의 방법을 사용해 보았지만 같은 문제가 발생했습니다. "시간 확인"이 성공하더라도 핸들러 내의 코드는 실행하는 데 시간이 걸리므로 보장 할 수 없습니다. –

관련 문제