comment utiliser Timer en C#

j'utilise system.Timers.Timer pour créer une minuterie.

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 + ": hellon");
}

récepteur dans la fonction send est un paramètre que je dois définir quand la fonction est utilisée, mais quand j'ajoute un paramètre dans la fonction send, comme:

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

alors il lance une erreur. Après que J'ai vérifié le MSDN, il a dit ElapsedEventArgs est seulement disponible pour ces fonctions qui ne produiront pas de données.

Comment puis-je résoudre ce problème? Mon programme n'est pas windows.Forme, donc je ne peux pas utilisez le System.Windows.Forms.Timer.

16
demandé sur pbaris 2012-06-19 07:29:41

3 réponses

Vous ne pouvez pas passer des paramètres supplémentaires pour le gestionnaire d'événement de rappel, parce que vous n'êtes pas en l'appelant -- la Minuterie est; c'est toute la question ;-)

Mais, vous pouvez facilement obtenir le même effet avec une fermeture:

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");
}

maintenant le handler écoulé est le (timerSender, timerEvent) => lambda action, qui se ferme sur le receiver variable et appelle send manuellement avec le paramètre supplémentaire chaque fois que la lambda est déclenchée.

Dans votre cas particulier, vous pas besoin du tout de l'expéditeur ou des arguments, donc il n'y a pas besoin de les transmettre. Le code devient:

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 vous vous interrogez sur les frais généraux de tout cela, c'est assez minime. Lambdas sont juste du sucre syntaxique et sont des fonctions simples dans les coulisses (avec un certain emballage de délégué automatique jeté dans pour le truc de l'événement). Les fermetures sont implémentées en utilisant des classes générées par le compilateur, mais vous ne remarquerez pas de gonflage de code à moins que vous ayez vraiment un ton de ils.

comme indiqué dans les commentaires, vous semblez accéder à un élément de L'interface utilisateur dans OnTimerElapsed code -- puisque vous n'utilisez pas de timer Windows Forms, il y a de fortes chances que vous obteniez une exception en faisant cela puisque le code s'exécute sur le thread dans lequel le timer s'exécute quand il déclenche l'événement -- et les commandes de L'interface utilisateur dans Windows accessible le fil qui les a créés.

vous pourriez jouer avec this.Invoke pour le corriger manuellement, mais il est plus facile d'avoir le timer marshall l'événement au bon thread pour vous via le SynchronizingObject propriété:

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;
}

enfin, suite à un autre commentaire, voici une autre façon de stocker une référence à la fermeture pour que vous puissiez vous désabonner de l'événement plus tard:

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;
}
20
répondu Cameron 2014-07-31 08:54:15

Vous ne pouvez pas passer des paramètres supplémentaires à un gestionnaire d'événements comme ça.

stockez votre valeur dans une variable de niveau d'objet pour qu'elle soit accessible dans le gestionnaire d'événements.

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");
}
3
répondu nunespascal 2012-06-19 03:37:20
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)
    {

    }
}
2
répondu SATTHESH TG 2017-07-24 09:09:08