C# 实现 倒计时 (一)

C# 的定时器的实现方法有 3 种:

(1)使用 System.Windows.Forms.Timer

(2)使用 System.Threading.Timer

(3)使用 System.Timers.Timer

其中:

System.Windows.Forms.Timer 只能在 WinForm 中使用,通过Windows消息机制实现的,类似于 VB 或 Delphi 中的 Timer 控件,内部使用 API  SetTimer 实现的。

它的主要缺点是计时不精确,而且必须有消息循环,因此在 Console  Application (控制台应用程序)中无法使用。

System.Timers.Timer 和 System.Threading.Timer 非常类似,它们是通过.NET  Thread  Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。

System.Timers.Timer 还可以应用于WinForm,完全取代上面的 Timer 控件。

它们的缺点是不支持直接的拖放,需要手工编码。

 

说明:在控制台下,如果要看得到 倒计时 的效果,需要在最后加一句 Console.ReadLine(); ,否则是看不到效果的(参下)。

 

先讲讲

 System.Timers.Timer 的使用:

MSDN 的示例:

//Timer.cs
using System;
using System.Timers;

public class Timer1
{
    //定义一个 类级别 的 Timer
    private static System.Timers.Timer aTimer;
    //如果 不是 类级别 的 Timer,我们应该使用 GC.KeepAlive(aTimer); 来维持变量的存在。
    //一般建议定义成 类级别 的 Timer

    public static void Main()
    {
        //局部的 Timer
        //System.Timers.Timer aTimer;

        //初始化 aTimer ,间隔时间为 10s
        aTimer = new System.Timers.Timer(10000);

        //添加一个钩子:注册一个函数,在倒计时完成后调用
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

        //设置 倒计时 的时间为 2s
        aTimer.Interval = 2000;

        //设置 是否 循环执行:默认会循环执行
        aTimer.AutoReset = true;

        //开启 倒计时
        aTimer.Enabled = true;

        Console.WriteLine("按下回车结束程序");
        Console.ReadLine();

        //防止局部的 aTimer 被 自动垃圾回收
        //GC.KeepAlive(aTimer);
    }

    // Specify what you want to happen when the Elapsed event is 
    // raised.
    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
    }
}

/* 大致输出结果如下:

按下回车结束程序
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
 */

如果你启动多个线程,问题就来了,两个线程的变化是同步的,这不是我们要的,

因此,我们给它加个线程锁:

//Program.cs

namespace CK
{
    class Program
    {
        static void Main(string[] args)
        {
            Clock.GetTimerStart();
        }
    }
}

//Clock.cs
using System;
using System.Timers;

namespace CK
{
    class Clock
    {
        //用于设置 线程锁
        private static object lockClock = new Object();

        //定义 类级别 的 Timer
        private static Timer clockTimer = new Timer();

        //检查是否有锁
        private static bool check = false;

        internal static void GetTimerStart()
        {
            //设置间隔时间
            clockTimer.Interval = 6000;
            //添加钩子:注册一个函数,在倒计时完成后调用
            clockTimer.Elapsed += new ElapsedEventHandler(Update);
            //设置循环调用
            clockTimer.AutoReset = true;
            //开启 倒计时
            clockTimer.Enabled = true;

            Console.WriteLine("按下回车结束程序");
            Console.ReadLine();
        }

        private static void Update(object sender, ElapsedEventArgs e)
        {
            //此处语义:如果 lockClock 未上锁,则上锁并执行 代码
            lock (lockClock)
            {
                if (check == false)
                {
                    check = true;
                    Console.WriteLine(e.SignalTime);
                }
                else
                {
                    //如果在此处无 return; 我们的代码就只能在 if 中调用
                    return;
                }
            }

            //Console.WriteLine(e.SignalTime);

            //同样在 未上锁 时执行,之所以加 lock,是避免上面的代码未执行完毕就执行此处
            //虽然在本例子中 有无加 lock 没有差别
            lock (lockClock)
            {
                check = false;
            }
        }

    }
}



已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页