在多线程中,有一个比较特殊的应用,就是计时器(Timer)。我在之前的一篇笔记中说过关于Timer控件的简单用法,这里我再根据一些新找的的内容,进行一些整理与扩展。
命名空间:
这里可以看出,基本上每一个大类的应用都有其自己的Timer。而在这四个不同的Timer命名空间中的Timer中,在基础用法上,并没有看到有什么特殊的不同。
无论什么Timer,其最主要的还是Elapsed事件,与Start、Stop这两个方法。当然,还有多线程环境下的问题。
由于每一次当Timer的时间间隔到的时候,都会引发Elapsed事件,然后我们就可以在这个事件中写入相应的操作,来完成我们想要完成的任务了。
由于,每一次都会新开启一个线程来执行Elapsed事件中的操作,所以,在使用Timer的时候,就像之前的笔记中记录的一样,对于共享资源的同步上要进行相应的同步处理才好。不然就会引起不可预知的问题。
在使用Timer的时候,还要注意的是对于时间间隔的控制,这主要涉及到的CPU与内存的问题。
如果我们所要执行的操作很多,而时间间隔又设置的很短的话,就会造成不断的开启线程,并且不断的执行操作的问题。不断的开启线程,就会造成内存越来越多的问题,这里如果处理不好,很可能会导致整个系统的崩溃,而且在一旦这些操作中,有写入资源的操作,那么还很有可能造成死锁的情况。
所以在设计Timer的时候,一定要明确这样几件事情:
- 要定时执行的操作,一定要尽可能的短
- 如果有必要,就对Timer的正在执行的数量进行一定的控制
- 一定要有资源同步的控制,最起码,要有对同一个操作进行完结性检查后,再去执行
「MSDN示例」 public class Class1 { static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); static int alarmCounter = 1; static bool exitFlag = false; // This is the method to run when the timer is raised. private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs) { myTimer.Stop(); // Displays a message box asking whether to continue running the timer. if(MessageBox.Show("Continue running?", "Count is: " + alarmCounter, MessageBoxButtons.YesNo) == DialogResult.Yes) { // Restarts the timer and increments the counter. alarmCounter +=1; myTimer.Enabled = true; } else { // Stops the timer. exitFlag = true; } } public static int Main() { /* Adds the event and the event handler for the method that will process the timer event to the timer. */ myTimer.Tick += new EventHandler(TimerEventProcessor); // Sets the timer interval to 5 seconds. myTimer.Interval = 5000; myTimer.Start(); // Runs the timer, and raises the event. while(exitFlag == false) { // Processes all the events in the queue. Application.DoEvents(); } return 0; } }
「MSDN示例」<asp:Timer Enabled="True|False" EnableTheming="True|False" EnableViewState="True|False" ID="string" Interval="integer" OnDataBinding="DataBinding event handler" OnDisposed="Disposed event handler" OnInit="Init event handler" OnLoad="Load event handler" OnPreRender="PreRender event handler" OnTick="Tick event handler" OnUnload="Unload handler" runat="server" SkinID="string" Visible="True|False" />
「MSDN示例」<%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Timer Example Page</title> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { OriginalTime.Text = DateTime.Now.ToLongTimeString(); } protected void Timer1_Tick(object sender, EventArgs e) { StockPrice.Text = GetStockPrice(); TimeOfPrice.Text = DateTime.Now.ToLongTimeString(); } private string GetStockPrice() { double randomStockPrice = 50 + new Random().NextDouble(); return randomStockPrice.ToString("C"); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:Timer ID="Timer1" OnTick="Timer1_Tick" runat="server" Interval="10000" /> <asp:UpdatePanel ID="StockPricePanel" runat="server" UpdateMode="Conditional"> <Triggers> <asp:AsyncPostBackTrigger ControlID="Timer1" /> </Triggers> <ContentTemplate> Stock price is <asp:Label id="StockPrice" runat="server"></asp:Label><BR /> as of <asp:Label id="TimeOfPrice" runat="server"></asp:Label> </ContentTemplate> </asp:UpdatePanel> <div> Page originally created at <asp:Label ID="OriginalTime" runat="server"></asp:Label> </div> </form> </body> </html>