如何使用定时器在C# [英] how to use Timer in C#

查看:180
本文介绍了如何使用定时器在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 system.Timers.Timer 以创建一个定时器。

I'm using system.Timers.Timer to create a 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)

然后,它抛出一个错误。我查了MSDN后,它说ElapsedEventArgs仅适用于这些功能,不会产生数据。

Then it throws an error. After I checked the MSDN, it said ElapsedEventArgs is only available for these function which won't produce data.

我该如何解决这个问题?我的计划是不是windows.Form,所以我不能使用 System.Windows.Forms.Timer

How can I solve this problem? My program isn't the windows.Form, so I cannot use the 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; 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");
}

现在经过的处理程序是(timerSender,timerEvent)=> 拉姆达行动,这将关闭在接收变量和调用发送手动每当拉姆达触发额外的参数。

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.

在您的特定情况下,你并不需要在所有的发送者或参数,所以没有必要转发。在code变为:

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

如果你想知道这一切的开销,这是pretty微乎其微。 Lambda表达式只是语法糖,并在幕后普通函数(带扔在事件东西一些自动委托包装)。瓶盖使用编译器生成的类来实现,但你不会看到任何code膨胀,除非你真正拥有的的他们。

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). Closures are implemented using compiler-generated classes, but you won't notice any code bloat unless you truly have a ton of them.

正如评论指出的那样,你似乎是在访问了 OnTimerElapsed code UI元素 - 因为你不使用Windows窗体计时器,有一个很好的机会,你会做这个,因为code将任何线程计时器发生时,它触发事件中运行运行得到一个异常 - 和UI控件在Windows中的必须进行访问的只有的从创建它们的线程。

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.

您可以用 this.Invoke 浪费时间手动修复它,但它更容易有计时器马歇尔通过的 SynchronizingObject的属性

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:

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

这篇关于如何使用定时器在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆