在System.timers.timer中给定时器触发的Elapsed事件传递参数

本文介绍了一种在C#中使用自定义定时器传递额外参数的方法。通过继承System.Timers.Timer并添加自定义属性,使得定时器触发事件时能够携带特定任务所需的参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个项目中用到大量的定时器,用来做定时的任务。比如定时给某个客户发送短信之类的。现在定时器触发事件之后需要给事件传递一个参数过去。其中可能包括这个任务的一些必需的信息,System.Timers.Timer的事件处理方法如下:

public abstract void TimerEvent(object sender, ElapsedEventArgs e);

先看了看 timer,和ElapsedEventArgs 中有没有能利用起来的属性。发现不可能。

于是 打算继承 ElapsedEventArgs ,用来传递参数。但是找不到设置timer发送继承之后的ElapsedEventArgs 的方法,这种办法也不行。

最后继承System.Timers.Timer

using System;

namespace TaskSchedulerManager
{
///
/// 自定义定时器
///
public class TaskTimer : System.Timers.Timer
{
#region <变量>
///
/// 定时器id
///
private int id;
///
/// 定时器参数
///

private string param ;
#endregion

#region <属性>
///
/// 定时器id属性
///
public int ID
{
set{id = value;}
get{return id;}
}
///
/// 定时器参数属性
///
public string Param
{
set{param = value;}
get{return param;}
}
#endregion

///
/// 构造函数
///
public TaskTimer() : base ()
{

}

}
}

然后在事件处理方法中:将sender 转型为System.timers.timer

///
/// timer Elapsed事件的处理方法
///
///


///
public override void TimerEvent(object sender, System.Timers.ElapsedEventArgs e)
{
//Console.WriteLine("DllTwo:" + DateTime.Now.ToString());

TaskSchedulerManager.TaskTimer tt = (TaskTimer)sender;
Console.WriteLine("id : " + tt.ID);
Console.WriteLine("Param: " + tt.Param);
}

<think>嗯,用户现在问的是System.Timers.Timer和时间触发的函数是否在同一个线程运行。我需要先回忆一下.NET中不同Timer的区别。System.Timers.Timer是基于System.ComponentModel.Component的,通常用于服务器环境。它的Elapsed事件默认是在线程池线程上触发的,也就是说回调函数不会在原来的线程执行。 不过用户可能不太清楚不同Timer之间的区别,比如和System.Threading.Timer或者System.Windows.Forms.Timer的区别。可能用户之前使用的是Windows Forms的Timer,那种是在UI线程触发,所以回调函数在UI线程,而System.Timers.Timer不同。用户的问题可能源于遇到了跨线程访问UI控件的问题,或者想知道定时器的回调是否会影响主线程的性能。 我需要确认用户是否了解线程池的概念,可能他们关心的是多线程环境下代码的执行情况。比如,如果在Elapsed事件处理中访问了UI元素,而没有使用Invoke,会导致异常,这时候用户可能会困惑为什么有时候能运行,有时候报错。 另外,用户的问题可能涉及到对异步编程和线程安全的理解。需要解释清楚System.Timers.Timer的工作机制,以及如何确保在回调函数中正确处理线程间的交互。可能需要给出示例,说明如何在不同线程间同步数据,或者提醒用户注意线程安全问题。 还要考虑用户的实际应用场景,比如是桌面应用还是服务端应用。如果是桌面应用,可能需要建议使用DispatcherTimer(WPF)或者Windows.Forms.Timer,以确保回调在UI线程执行。如果是服务端,System.Timers.TimerSystem.Threading.Timer可能更合适。 最后,需要明确回答用户的问题:System.Timers.Timer的回调函数不在原来的线程,而是由线程池线程执行,因此不是同一线程。同时要提醒可能的线程安全问题,并给出解决方案或建议。</think>在 .NET 中,`System.Timers.Timer` 的**时间触发函数(Elapsed 事件)默认不在主线程执行**,而是由线程池(ThreadPool)中的线程触发。以下是详细解释: --- ### **1. 线程行为** - **`System.Timers.Timer` 的工作机制**: - 当定时器启动后,它会通过线程池分配一个后台线程,在指定时间间隔触发 `Elapsed` 事件。 - **每次触发事件时,线程池可能会分配不同的线程**(取决于线程池调度)。 - **简单验证代码**: ```csharp var timer = new System.Timers.Timer(1000); timer.Elapsed += (sender, e) => { Console.WriteLine($"Elapsed 事件线程ID: {Thread.CurrentThread.ManagedThreadId}"); }; timer.Start(); Console.WriteLine($"主线程ID: {Thread.CurrentThread.ManagedThreadId}"); Console.ReadLine(); ``` **输出结果**: ``` 主线程ID: 1 Elapsed 事件线程ID: 4 Elapsed 事件线程ID: 5 // 下次触发可能换线程 ``` --- ### **2. 与其他 Timer 的对比** | Timer 类型 | 触发线程 | 适用场景 | |--|-----------------------|-------------------------| | `System.Timers.Timer` | 线程池线程(默认) | 服务端、后台任务 | | `System.Threading.Timer` | 线程池线程 | 低开销定时任务 | | `System.Windows.Forms.Timer` | UI 线程(主线程) | Windows Forms 界面更新 | | `System.Timers.Timer` + 同步化| 主线程(需手动同步) | 需要操作 UI 的后台逻辑 | --- ### **3. 如何强制在特定线程执行?** 若需要将 `Elapsed` 事件逻辑同步到主线程(如操作 UI): - **在 WPF 中**: ```csharp timer.Elapsed += (sender, e) => { Application.Current.Dispatcher.Invoke(() => { // 此处代码在 UI 线程执行 label.Text = "Updated"; }); }; ``` - **在 WinForms 中**: ```csharp timer.Elapsed += (sender, e) => { this.Invoke((Action)(() => { // 此处代码在 UI 线程执行 label.Text = "Updated"; })); }; ``` --- ### **4. 注意事项** 1. **线程安全问题**: - 若 `Elapsed` 事件中访问共享资源(如集合、文件),需使用锁(`lock`)或其他同步机制。 2. **定时器精度**: - 线程池调度和系统负载可能导致触发时间有微小误差(不适合高精度计时)。 3. **资源释放**: - 使用后需调用 `timer.Stop()` 和 `timer.Dispose()`,避免内存泄漏。 --- ### **5. 总结** - **默认行为**:`System.Timers.Timer` 的 `Elapsed` 事件在**线程池线程**触发,与主线程不同。 - **需要操作 UI**:必须通过 `Dispatcher` 或 `Control.Invoke` 同步到主线程。 - **替代方案**:若需直接在 UI 线程触发事件,可改用 `System.Windows.Forms.Timer`(WinForms)或 `DispatcherTimer`(WPF)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值