2012-06-19 13 views
15

estoy usando system.Timers.Timer para crear un temporizador.cómo utilizar temporizador en C#

public System.Timers.Timer timer = new System.Timers.Timer(200); 
private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Enabled = true; 
    timer.Elapsed += new System.Timers.ElapsedEventHandler(send); 
    timer.AutoReset = true; 
} 

public void send(object source, System.Timers.ElapsedEventArgs e) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 

El receptor en función de envío es un parámetro que tengo que configurar cuando se utiliza la función, pero cuando agrego un parámetro en la función de envío, como:

public void send(object source, System.Timers.ElapsedEventArgs e,string receiver) 

Entonces arroja un error. Después de consultar el MSDN, dijo que ElapsedEventArgs solo está disponible para estas funciones que no generarán datos.

¿Cómo puedo resolver este problema? Mi programa no es Windows.Form, por lo que no puedo usar el System.Windows.Forms.Timer.

+0

Bueno, se puede utilizar el 'System.Windows.Forms.Timer' si se añade una referencia a la biblioteca. – annonymously

+0

relacionado [cómo pasar el parámetro del remitente al system.timers.timer] (http://stackoverflow.com/questions/6368399/how-to-pass-the-the-sender-parameter-to-the-system -timers-timer) – Damith

+0

No debe utilizar System.Windows.Timer con ningún componente UI (por ejemplo, rtbMsg.AppendText es probable que acceda a algún tipo de control de Windows), System.Timer.Elapsed se invoca en un subproceso no UI y causará una excepción en la mayoría de los casos. Si no es WinForms y es WPF, querrá usar un DispatchTimer. Si puede aclarar qué error está recibiendo, alguien podría ofrecerle un consejo más exacto. –

Respuesta

19

No se puede pasar parámetros adicionales para la devolución de llamada controlador de eventos, ya que no es la persona llamándola - el temporizador está; que es el punto ;-)

embargo, puede fácilmente lograr el mismo efecto con un cierre:

private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Elapsed += (timerSender, timerEvent) => send(timerSender, timerEvent, receiver); 
    timer.AutoReset = true; 
    timer.Enabled = true; 
} 

public void send(object source, System.Timers.ElapsedEventArgs e, string receiver) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 

Ahora el controlador transcurrido es la acción (timerSender, timerEvent) => lambda, que se cierra sobre la receiver variable y llama send manualmente con el parámetro extra siempre que se active la lambda.

En su caso particular no necesitan que el remitente o argumentos en absoluto, así que no hay necesidad de reenviarlos. El código se convierte en:

private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Elapsed += (s_, e_) => OnTimerElapsed(receiver); 
    timer.AutoReset = true; 
    timer.Enabled = true; 
} 

private void OnTimerElapsed(string receiver) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 

Si se está preguntando sobre la sobrecarga de todo esto, es bastante mínimo. Las lambdas son simplemente azúcar sintáctico y son funciones simples detrás de escena (con algunos envoltorios de delegados automáticos para las cosas del evento). Los cierres se implementan utilizando clases generadas por el compilador, pero no notará ningún tipo de hinchamiento de código a menos que realmente tenga un ton de ellos.

Como se indicó en los comentarios, parece que está accediendo a un elemento de IU en el código OnTimerElapsed - ya que no está utilizando un temporizador de Windows Forms, hay una gran probabilidad de que obtenga una excepción al hacerlo desde el código se ejecutará en cualquier hilo del temporizador pasa a estar corriendo en cuando se activa el evento - y los controles de interfaz de usuario de Windows debe ser visitada solamente de la rosca que los creó.

Usted podría perder el tiempo con this.Invoke para fijar de forma manual, pero es más fácil tener el temporizador Marshall el evento para el hilo adecuado para usted a través de la SynchronizingObject property:

private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.SynchronizingObject = this; // Assumes `this` implements ISynchronizeInvoke 
    timer.Elapsed += (s_, e_) => OnTimerElapsed(receiver); 
    timer.AutoReset = true; 
    timer.Enabled = true; 
} 

Por último, se le solicita por otro comentario, aquí hay otra forma en que podría almacenar una referencia al cierre de manera que puede darse de baja del acontecimiento posterior:

private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.SynchronizingObject = this; // Assumes `this` implements ISynchronizeInvoke 
    ElapsedEventHandler onElapsed; 
    onElapsed = (s_, e_) => { 
     timer.Elapsed -= onElapsed; // Clean up after firing 
     OnTimerElapsed(receiver); 
    }; 
    timer.Elapsed += onElapsed; 
    timer.AutoReset = true; 
    timer.Enabled = true; 
} 
+0

¿Por qué iniciar el temporizador antes de configurar el autoreset y devolver la llamada? timer.Enabled = true debería ser lo último que haga – nbrooks

+0

@nbrooks: Buen punto, solo estaba copiando el código de OP. Voy a editar eso en – Cameron

+0

@nbrooks ¿es lo mismo que timer.Start()? – Damith

3

no se puede pasar parámetros adicionales a un controlador de eventos como ese.

tienda de su valor en una variable de nivel de objeto de modo que se puede acceder en el controlador de eventos.

private string receiver; 

public System.Timers.Timer timer = new System.Timers.Timer(200); 
private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Enabled = true; 
    receiver = 'your val'; 
    timer.Elapsed += new System.Timers.ElapsedEventHandler(send); 
    timer.AutoReset = true; 
} 

public void send(object source, System.Timers.ElapsedEventArgs e) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 
2
public partial class Form2 : Form 
{ 
    Timer timer = new Timer(); 
    public Form2() 
    { 
     InitializeComponent(); 
     timer.Tick += new EventHandler(timer_Tick); // Every time timer ticks, timer_Tick will be called 
     timer.Interval = (10) * (1000);    // Timer will tick every 10 seconds 
     timer.Start();        // Start the timer 
    } 
    void timer_Tick(object sender, EventArgs e) 
    { 
     //MessageBox.Show("Tick");     // Alert the user 
     var time = DateTime.Now; 
     label1.Text = $"{time.Hour} : {time.Minute} : {time.Seconds} : {time.Milliseconds}"; 
    } 
    private void Form2_Load(object sender, EventArgs e) 
    { 

    } 
} 
Cuestiones relacionadas