C#定时器

在Framework中存在着4种定时器:其中分为两类,

多线程计时器

1:System.Threading.Timer

2:System.Timers.Timer

特殊目的的单线程计时器:

1:System.Windows.Forms.Timer(Windows Forms Timer)

2:System.Windows.Threading.DispatcherTimer(WPF timer);

多线程计时器比较强大,精确,而且可扩展性强;

单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。

System.Threading.Timer是最简单的多线程计时器。在下面的例子中,定时器在5秒后开始定时1秒的调用Tick方法。

public static void Main ()
{
//5秒后开始运行,接着每隔1秒的调用Tick方法
Timer tmr = new Timer(Tick, "tick...", 5000, 1000);
Console.ReadLine();
tmr.Dispose();
}
static void Tick(object data)
{
Console.WriteLine(data);
}

.net framework提供的另一个计时器System.Timers.Timer.简单的对System.Threading.Timer进行了包装。增加了下面几个特性。

  • 实现了Component,所以可以在设计器显示。
  • 代替Change方法的一个Interval属性
  • 代替callback委托的一个Elapsed事件
  • 启动和停止timer的Enabled属性,默认是false。
  • 为了避免Enabled造成混乱,提供了Start和Stop方法。
  • 是否在每次指定的间隔结束时引发Elapsed时间,还是仅间隔第一次结束后运行的AutoReset属性。
  • 在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。
public static void MainThread()
{
Timer tmr = new Timer();
tmr.Interval = 500;
tmr.Elapsed += new ElapsedEventHandler(tmr_Elapsed);
tmr.Start();
Console.ReadLine();
tmr.Stop();
Console.ReadLine();
tmr.Start();
Console.ReadLine();
tmr.Dispose();
}

static void tmr_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Tick...");

  单线程计时器:

1:System.Windows.Forms.Timer(Windows Forms Timer)

2:System.Windows.Threading.DispatcherTimer(WPF timer);

单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个Windows服务应用程序中使用Windows Forms的Timer,timer 事件并不会被触发,只有在对应的环境下才会被触发。

像System.Timers.Timer一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同,

WPF和Windows Forms的计时器使用消息循环机制来取代线程池产生消息的机制。

这意味着Tick事件总是在创建timer的那个线程上执行,同时也意味着如果上一个Tick消息还未被处理,即使时间超过了间隔时间,在消息循环中也只存在一个Tick消息。

下面是它们的优点:

  1. 你可以忘记线程安全。
  2. 一个Tick事件在前一个Tick事件被处理完毕前不会被触发。
  3. 你可以直接在Tick事件处理代码中更新控件,不需要调用Control.Invoke或Dispatcher.Invoke.

看下在Winform中使用单线程定时器的效果:

//基于Windows消息循环的单线程计时器
private System.Windows.Forms.Timer timer = new Timer() { };

public Form1()
{
InitializeComponent();

timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;
}

void timer_Tick(object sender, EventArgs e)
{
//模拟的做一些耗时的操作
System.Threading.Thread.Sleep(2000);
}

如果运行上面的代码,会发现UI界面响应速度很慢,

原理上面已经介绍了:单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。

解决这个问题的方法是使用多线程计时器:只要修改代码使用多线程计时器即可:

//使用多线程计时器
private System.Timers.Timer timer = new System.Timers.Timer();

public Form1()
{
InitializeComponent();

timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//模拟的做一些耗时的操作
System.Threading.Thread.Sleep(2000);
}

上面的例子告诉我们单线程计时器的缺点:

除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。

所以 WPF和Windows Forms的计时器都非常适合小任务,尤其是界面更新的任务。例如时钟和计数显示。否则,你需要一个多线程计时器

### C#定时器的实现方式 在 C# 编程语言中,可以通过多种方法来实现定时器功能。这些方法适用于不同的场景和需求,下面详细介绍几种常见的实现方式。 #### 方法一:使用 `System.Timers.Timer` 类 这是最常用的定时器实现之一,适合于需要按固定时间间隔执行某些操作的任务。通过设置属性如 `Interval` 和 `AutoReset` 来控制定时器的行为[^3]。 ```csharp using System; using System.Timers; namespace Test2 { internal class Program { private static System.Timers.Timer Timer; static void Main(string[] args) { Timer = new System.Timers.Timer(); Timer.Interval = 2000; // 设置时间为2000毫秒(即2秒) Timer.AutoReset = true; // 是否自动重置并重复执行 Timer.Elapsed += Timer_Elapsed; // 绑定事件处理程序 Timer.Enabled = true; // 启动定时器,也可以用 Timer.Start() Console.WriteLine("Press any key to exit..."); Console.ReadKey(); // 阻塞主线程以便观察效果 } private static void Timer_Elapsed(object sender, ElapsedEventArgs e) { Console.WriteLine("定时器触发: " + DateTime.Now.ToString()); } } } ``` 此代码展示了如何创建一个每两秒钟打印当前时间的简单定时器。 --- #### 方法二:使用线程 (`Thread`) 和休眠 (`Sleep`) 这种方法利用多线程技术,在单独的线程中运行目标逻辑,并通过 `Thread.Sleep()` 让线程暂停一段时间后再继续执行[^1]。 ```csharp using System; using System.Threading; class ThreadTimerExample { public static void Main() { while (true) { Console.WriteLine("每隔一秒执行一次"); Thread.Sleep(1000); // 暂停1000毫秒(即1秒) } } } ``` 虽然这种方式易于理解,但它可能不如其他高级机制高效或灵活。 --- #### 方法三:基于异步任务 (`Task.Delay`) 对于现代应用程序开发而言,推荐采用这种更简洁且非阻塞性的方式完成相同目的——借助 .NET 的 Task 并行库以及延迟函数。 ```csharp using System; using System.Threading.Tasks; public class AsyncTimerExample { public async Task RunAsyncTimer(int intervalMilliseconds) { while (true) { await Task.Delay(intervalMilliseconds); Console.WriteLine($"定时任务已触发 @ {DateTime.Now}"); } } public static void Main(string[] args) { var example = new AsyncTimerExample(); _ = example.RunAsyncTimer(500).ConfigureAwait(false); Console.WriteLine("按下任意键退出..."); Console.ReadLine(); } } ``` 上述例子说明了怎样构建一个持续循环直到手动终止的应用程序;每次等待半秒钟之后再次显示消息给用户看。 --- ### 关于高精度的需求 如果项目中有更高精度的要求,则需考虑专门设计用来满足此类特殊场合下的工具比如 Multimedia Timers 或者 Performance Counters 等[^5]。不过一般情况下,默认提供的几个组件已经能够很好地覆盖大部分日常所需范围之外的情况了。 --- ### 总结 综上所述,C# 提供了丰富的 API 支持开发者根据不同业务特点选用合适的方案去达成预期目标。无论是基础版还是增强型版本都能找到对应的最佳实践案例可供参考学习[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值