2010-10-31 148 views
19

我基本上想要一個調度器計時器對象只能執行一次。DispatcherTimer tick一次

所以我的基本代碼:

DispatcherTimer dispatcherTimer = new DispatcherTimer(); 
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); 
dispatcherTimer.Interval = new TimeSpan(0, 0, 4); 
dispatcherTimer.Start(); 

然後單擊事件中:

private void dispatcherTimer_Tick(object sender, EventArgs e) 
     { 
      this.Visibility = System.Windows.Visibility.Visible; 
      // Now stop timer execution.. or kill the timer object 
     } 

如何停止計時器或該執行後殺死的對象?

回答

32
private void dispatcherTimer_Tick(object sender, EventArgs e) 
     { 
      this.Visibility = System.Windows.Visibility.Visible; 
      (sender as DispatcherTimer).Stop(); 
     } 
6
private void dispatcherTimer_Tick(object sender, EventArgs e) 
     { 
      this.Visibility = System.Windows.Visibility.Visible; 
      var dispatcherTimer = (DispatcherTimer)sender; 
      dispatcherTimer.Stop(); 
     }  
21

下面是一個使用lambda表達式替代代碼:

var timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(4)}; 
timer.Tick += (sender, args) => 
{ 
    this.Visibility = System.Windows.Visibility.Visible; 
    timer.Stop(); 
}; 

timer.Start(); 
+0

無法垃圾收集得到事件觸發之前擺脫了計時器的? – Cameron 2014-04-29 18:04:13

+0

@Cameron,沒有,因爲計時器現在引用了匿名函數,因此它不能被垃圾收集。 – 2014-04-29 18:11:29

+1

沒錯,但還有其他人提到那個匿名函數嗎?不能*也被收集起來? – Cameron 2014-04-29 18:13:45

2

答案可能工作了,但你應該分離從Tick事件的事件監聽器,當你不需要計時器不再。我不信任eventhandler和垃圾收集器;)

我把這個漂亮的DispatcherTimer子類放到了一個簡單的tick類定時器中。

public class DispatcherTimeout : DispatcherTimer 
{ 
    #region Constructors and Destructors 

    protected DispatcherTimeout(DispatcherPriority priority) 
     : base(priority) 
    { 
    } 

    #endregion 

    #region Public Properties 

    public Action<DispatcherTimeout> Callback { get; set; } 

    #endregion 

    #region Public Methods and Operators 

    /// <summary> 
    /// Instantiates a new DispatcherTimeout and starts it. 
    /// </summary> 
    /// <param name="priority"> 
    /// The dispatcher priority used for the timer. 
    /// </param> 
    /// <param name="duration"> 
    /// The duration. 
    /// </param> 
    /// <param name="callback"> 
    /// The callback which should be called on tick. 
    /// </param> 
    /// <returns> 
    /// An instance of DispatcherTimeout. 
    /// </returns> 
    public static DispatcherTimeout Timeout(DispatcherPriority priority, TimeSpan duration, Action<DispatcherTimeout> callback) 
    { 
     var dispatcherTimeout = new DispatcherTimeout(priority); 
     dispatcherTimeout.Interval = duration; 
     dispatcherTimeout.Callback = callback; 

     dispatcherTimeout.Tick += dispatcherTimeout.HandleTick; 

     dispatcherTimeout.Start(); 

     return dispatcherTimeout; 
    } 

    #endregion 

    #region Methods 

    private void HandleTick(object sender, EventArgs e) 
    { 
     this.Stop(); 
     this.Tick -= this.HandleTick; 

     if (this.Callback != null) 
     { 
      this.Callback(this); 
     } 
    } 

    #endregion 
} 

例子:

DispatcherTimeout.Timeout(
    DispatcherPriority.Normal, 
    TimeSpan.FromSeconds(2.0), 
    timeout => 
    { 
     this.Visibility = System.Windows.Visibility.Visible; 
    }); 
0
/// <summary> 
    /// Fires an action once after "seconds" 
    /// </summary> 
    public static void FireOnce(float seconds, Action onElapsed) 
    { 
     Action detach = null; 
     var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(seconds) }; 

     var handler = new EventHandler((s, args) => 
     { 
      onElapsed(); 
      // Note: When stop is called this DispatcherTimer handler will be GC'd (eventually). There is no need to unregister the event. 
      timer.Stop(); 
      if (detach != null) 
       detach(); 
     }); 
     detach = new Action(() => timer.Tick -= handler); // No need for deregistering but just for safety let's do it. 

     timer.Tick += handler; 
     timer.Start(); 
    } 
+0

感謝Vlad的回答。 – 2017-05-10 16:10:34