2010-10-31 11 views
19

Básicamente, quiero que un objeto del temporizador del distribuidor ejecute solo una vez.DispatcherTimer marque una vez

Así que tienen el código básico:

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

Luego dentro del evento click:

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

¿Cómo puedo detener el temporizador o acabar con el objeto después de esta ejecución?

Respuesta

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

Aquí está el código alternativo que utiliza la expresión lambda:

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

timer.Start(); 
+0

se le fue el recolector de basura deshacerse del temporizador antes de que se desencadene el evento? – Cameron

+0

@Cameron, no porque el temporizador ahora tiene referencia a la función anónima, por lo tanto, no se puede recolectar basura. –

+1

Correcto, pero ¿quién más tiene una referencia a esa función anónima? ¿No se pudo * recoger * también? – Cameron

2

las respuestas podrían funcionar, pero se debe separar el detector de eventos de la garrapata de sucesos cuando no es necesario el temporizador por más tiempo . No confío en eventhandler y el recolector de basura;)

Utilicé esta buena subclase de DispatcherTimer para tener una clase conveniente para los temporizadores de un solo tic.

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 
} 

Ejemplo:

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édito a la respuesta de Vlad. –