2010-10-31 4 views
19

Je souhaite fondamentalement qu'un objet timer de dispatcher ne s'exécute qu'une seule fois.DispatcherTimer cocher une fois

J'ai donc le code de base:

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

Puis dans l'événement click:

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

Comment puis-je arrêter ou pour tuer l'objet après cette exécution?

Répondre

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

Voici code alternatif en utilisant l'expression lambda:

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

timer.Start(); 
+0

Impossible le garbage collector se débarrasser de la minuterie avant l'événement se déclenche? – Cameron

+0

@Cameron, non parce que le temporisateur a maintenant une référence à la fonction anonyme, donc il ne peut pas être collecté. –

+1

Bien, mais qui d'autre a une référence à cette fonction anonyme? Couldnt * that * être collecté aussi? – Cameron

2

les réponses pourraient travailler, mais vous devez détacher votre écouteur d'événement du Tick événement lorsque vous n'avez pas besoin de la minuterie plus longtemps . Je ne fais pas confiance à eventhandler et au garbage collector;)

Je voudrais que cette gentille sous-classe de DispatcherTimer ait une classe conviniente pour les minuteurs à un seul 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 
} 

Exemple:

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

Crédit à la réponse de Vlad. –

Questions connexes