C#中定时器的使用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11094008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to use Timer in C#
提问by psyche
I'm using system.Timers.Timerto 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 receiverin 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:
send函数中的receiver是我在使用函数时需要设置的参数,但是当我在send函数中添加参数的时候,比如:
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.
采纳答案by Cameron
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 ;-)
您不能将额外的参数传递给事件处理程序回调,因为您不是调用它的人——Timer 是;这就是重点;-)
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 receivervariable and calls sendmanually with the extra parameter whenever the lambda is triggered.
现在 Elapsed 处理程序是(timerSender, timerEvent) =>lambda 操作,它关闭receiver变量并send在触发 lambda 时使用额外参数手动调用。
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). Closures are implemented using compiler-generated classes, but you won't notice any code bloat unless you truly have a tonof them.
如果你想知道所有这些的开销,它非常小。Lambda 只是语法糖,是幕后的普通函数(为事件内容抛出了一些自动委托包装)。闭包是使用编译器生成的类实现的,但除非您真的拥有大量的闭包,否则您不会注意到任何代码膨胀。
As pointed out in the comments, you seem to be accessing a UI element in the OnTimerElapsedcode -- 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 mustbe accessed onlyfrom the thread that created them.
正如评论中指出的那样,您似乎正在访问OnTimerElapsed代码中的 UI 元素——由于您没有使用 Windows 窗体计时器,因此您很有可能通过这样做得到一个异常,因为代码将继续运行无论线程计时器发生火灾时该事件中运行-而在Windows UI控件必须访问只有从创建它们的线程。
You could mess around with this.Invoketo fix it manually, but it's easier to have the timer marshall the event to the right thread for you via the SynchronizingObjectproperty:
您可以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;
}
回答by nunespascal
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");
}
回答by SATTHESH TG
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)
{
}
}

