简体   繁体   English

如何在C#中使用Timer

[英]how to use Timer in C#

I'm using system.Timers.Timer to create a timer. 我正在使用system.Timers.Timer创建一个计时器。

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

The receiver in send function is a parameter that I need to set when the function is used, but when I add a parameter in the send function, like: 发送函数中的接收器是我在使用函数时需要设置的参数,但是当我在发送函数中添加参数时,如:

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

Then it throws an error. 然后它会抛出一个错误。 After I checked the MSDN, it said ElapsedEventArgs is only available for these function which won't produce data. 在我检查了MSDN之后,它说ElapsedEventArgs仅适用于这些不会产生数据的功能。

How can I solve this problem? 我怎么解决这个问题? My program isn't the windows.Form, so I cannot use the System.Windows.Forms.Timer . 我的程序不是windows.Form,所以我不能使用System.Windows.Forms.Timer

You can't pass extra parameters to the event handler callback, because you aren't the one calling it -- the Timer is; 你不能将额外的参数传递给事件处理程序回调,因为你不是那个调用它的人 - Timer是; that's the whole point ;-) 这就是重点;-)

But, you can easily accomplish the same effect with a closure: 但是,使用闭包可以轻松实现相同的效果:

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

Now the Elapsed handler is the (timerSender, timerEvent) => lambda action, which closes over the receiver variable and calls send manually with the extra parameter whenever the lambda is triggered. 现在,Elapsed处理程序是(timerSender, timerEvent) => lambda动作,它关闭receiver变量,并在每次触发lambda时使用extra参数手动调用send

In your particular case you don't need the sender or arguments at all, so there's no need to forward them. 在您的特定情况下,您根本不需要发件人或参数,因此无需转发它们。 The code becomes: 代码变成:

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

If you're wondering about the overhead of all this, it's pretty minimal. 如果你想知道所有这些的开销,它是非常小的。 Lambdas are just syntactic sugar and are plain functions behind the scenes (with some automatic delegate wrapping thrown in for the event stuff). Lambdas只是语法糖,并且是幕后的简单函数(为事件提供了一些自动委托包装)。 Closures are implemented using compiler-generated classes, but you won't notice any code bloat unless you truly have a ton of them. 瓶盖使用编译器生成的类实现,但你不会注意到任何代码膨胀,除非你真的有一他们。

As pointed out in the comments, you seem to be accessing a UI element in the OnTimerElapsed code -- since you're not using a Windows Forms timer, there's a good chance you'll get an exception by doing this since the code will run on whatever thread the timer happens to be running in when it fires the event -- and UI controls in Windows must be accessed only from the thread that created them. 正如评论中指出的那样,您似乎正在访问OnTimerElapsed代码中的UI元素 - 因为您没有使用Windows窗体计时器,所以您很可能会通过这样做获得异常,因为代码将运行在触发事件时计时器碰巧运行的任何线程 - 并且必须 仅从创建它们的线程访问Windows中的UI控件。

You could mess around with this.Invoke to fix it manually, but it's easier to have the timer marshall the event to the right thread for you via the SynchronizingObject property : 你可以搞乱这个。 this.Invoke手动修复它,但是让定时器通过SynchronizingObject属性将事件编组到正确的线程更容易:

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

Finally, prompted by another comment, here's another way you could store a reference to the closure so that you can unsubscribe from the event later: 最后,在另一条评论的提示下,这是另一种可以存储对闭包的引用的方法,以便您以后可以取消订阅该事件:

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

You can't pass extra parameters to an event handler like that. 您不能将额外的参数传递给这样的事件处理程序。

Store your value in an object level variable so that it can be accessed in the event handler. 将值存储在对象级变量中,以便可以在事件处理程序中访问它。

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

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM