when the project begin to run, please check the time , then set timer to your first elapsed time. Ok, when the time is go to your time you want, please kill the first timer, and set 2nd timer elapsed time 1 hour. Now, you can process your event every hour at the minute you want.
private void timer1_Tick(object sender, EventArgs e)
{
if (DateTime.Now.Minute == n)
{
...
}
}timer1的Interval 设为 60000 以下。
按你的需要假设每小时30分启动的,取得当前时间,如果已经过了30分,当前时间加1小时,分钟设置为30分,计算相差的秒数;否则,当前时间的分钟设置为30分,减去当前时间,计算相差的秒数,定时器在这个时间后启动,时间间隔为一小时,就可以满足你的需求了。以下代码实现由配置文件决定一个定时器何时启动和时间间隔
TextEx.IsNumeric 检查给出的string是否由数字组成
配置文件:app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ConnString" value="Data Source=(local);database=ResourcePlat;User ID=DBUser;Password=DBPassword;" />
<add key="StartTime" value="02:00:00" /><!-- 每天凌晨启动:value="00:00:00" | 每天早上4点10分启动:value="04:10:00" | 服务启动100秒后起到:value="100" -->
<add key="StartPeriod" value="0" /><!-- 每天运行一次:value="0" | 每100秒执行一次:value="100" | 每1小时执行一次:value="01:00:00"-->
<add key="LogPath" value="c:\installpath\Log\ResourceService\" />
<add key="debug" value="True" />
</appSettings>
</configuration> /// <summary>
/// 获取字符串格式的 TimeSpan 的毫秒数
/// 格式:24:00:00或以秒为单位的数字
/// </summary>
/// <param name="sTimeSpan">字符串格式的 TimeSpan</param>
/// <returns>秒数</returns>
public static long GetTimeTicks(string sTimeSpan)
{
int nHour=0, nMinute=0, nSecond=0;
return GetTimeTicks(sTimeSpan, ref nHour, ref nMinute, ref nSecond);
} /// <summary>
/// 获取字符串格式的 TimeSpan 的毫秒数,并返回时分秒
/// 格式:24:00:00或以秒为单位的数字
/// </summary>
/// <param name="sTimeSpan">字符串格式的 TimeSpan</param>
/// <param name="nHour"></param>
/// <param name="nMinute"></param>
/// <param name="nHour"></param>
/// <returns>秒数</returns>
public static long GetTimeTicks(string sTimeSpan,
ref int nHour, ref int nMinute, ref int nSecond)
{
long nTicks = 0;
nHour = nMinute = nHour =0; if (sTimeSpan == null)
return nTicks; if ((sTimeSpan.Length == 8) &&
(sTimeSpan[2] == ':') && (sTimeSpan[5] == ':'))
{
if ( IsNumeric(sTimeSpan.Substring(6,2))
&& IsNumeric(sTimeSpan.Substring(3,2))
&& IsNumeric(sTimeSpan.Substring(0,2)) )
{
nSecond = int.Parse(sTimeSpan.Substring(6,2));
nMinute = int.Parse(sTimeSpan.Substring(3,2));
nHour = int.Parse(sTimeSpan.Substring(0,2)); // 检查是否有错误的值
if (nSecond >= 60)
{
nSecond = 59;
}
if (nMinute >= 60)
{
nMinute = 59;
}
nTicks = nHour * 3600 + nMinute * 60 + nSecond ;
}
}
else
{
if (IsNumeric(sTimeSpan))
{
nTicks = long.Parse(sTimeSpan);
nHour = (int)(nTicks/3600);
nMinute = (int)((nTicks - nHour*3600)/60);
nSecond = (int)(nTicks - nHour*3600 - nMinute*60);
}
// else 不是数字,就返回默认值0
}
return nTicks;
} protected System.Threading.Timer m_SynchroTimer ; // 用于启动操作的定时器
protected void Start_SynchroTimer()
{
try
{
string sStartTime = ConfigurationSettings.AppSettings["StartTime"];
string sStartPeriod = ConfigurationSettings.AppSettings["StartPeriod"]; TimeSpan startTimerSpan; // 第一次启动定时器的时间间隔
TimeSpan periodTimerSpan; // 每次运行的时间间隔 // 启动一个定时器,执行资源同步
if (m_SynchroTimer!=null)
{
m_SynchroTimer.Dispose();
m_SynchroTimer = null;
} // 计算计时器间隔时间
long nTicks; // 24hour=86400*1000000
int nYear=0, nMonth=0, nDay=0, nHour=0, nMinute=0, nSecond=0; // 指定时间间隔运行
nTicks = TextEx.GetTimeTicks(sStartPeriod, ref nHour, ref nMinute, ref nSecond); // 如果转换失败或少于10分钟,就把运行时间间隔设置为一天
if (nTicks < 1) // 1Min = 60s(秒)
{
nDay = 1;
nHour=0; nMinute=0; nSecond=0;
} periodTimerSpan = new TimeSpan(nDay, nHour, nMinute, nSecond);
//CLogInfo.Log(periodTimerSpan.ToString()); // 计算开始计时时间
TextEx.GetTimeTicks(sStartTime, ref nHour, ref nMinute, ref nSecond); if (TextEx.IsNumeric(sStartTime))
{
startTimerSpan = new TimeSpan(nHour, nMinute, nSecond);
}
else // 不是由全部数字组成
{
// 每日运行
// 计算下一天的开始时间
DateTime dtNow = DateTime.Now;
nYear = dtNow.Year;
nMonth = dtNow.Month;
nDay = dtNow.Day;
DateTime nextStartTime = new DateTime(nYear, nMonth, nDay, nHour, nMinute, nSecond );
if (nextStartTime > DateTime.Now.AddMinutes(1))
{
startTimerSpan = nextStartTime-DateTime.Now;
}
else
{
startTimerSpan = nextStartTime.AddDays(1) - DateTime.Now;
}
} // Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate = new TimerCallback(SynchroTimer_Elapsed); // Create a timer that waits one second, then invokes every second.
m_SynchroTimer = new System.Threading.Timer(timerDelegate, null, startTimerSpan, periodTimerSpan);
CLogInfo.Log("The Synchro will be Started at ["+startTimerSpan.ToString()+"]\r\nEach run time:"+periodTimerSpan.ToString(), "Message...");
}
catch(Exception ex)
{
CLogInfo.Log(ex);
}
} protected void Stop_SynchroTimer()
{
// 终止定时器
if (m_SynchroTimer!=null)
{
m_SynchroTimer.Dispose();
m_SynchroTimer = null;
CLogInfo.Log("Synchro service Stop!", "Message...");
}
}
/// <summary>
/// 定时器回调函数,执行同步
/// </summary>
/// <param name="p"></param>
protected static void SynchroTimer_Elapsed(object p)
{
CLogInfo.Log("start SynchroTimer_Elapsed", "Message...");
int nResult = CSynchro.ExecuteSynchro();
CLogInfo.Log("CSynchro.ExecuteSynchro() return:"+nResult.ToString(), "Message...");
}
System.Threading.Timer
System.Timers.Timer
System.Windows.Forms.Timer
第一个定时器(System.Threading.Timer)是线程安全的,但需要回调方法。我不太熟悉。
第二个定时器(System.Timers.Timer)只有静态成员才是线程安全的,不过它是基于服务器的组件,通常用于关键性服务器,可以很精确地计时。而其据说它甚至不使用任何线程(忘了拒谁说的了),效率相当高。不过它是通过Elapsed事件实现定时的。看起来这个最适合你。
第三个定时器(System.Windows.Forms.Timer)正如它的命名空间所表示的,它是一个控件。同样只有静态成员是线呈安全的。它占用用户的UI消息泵,而且只能在同一个线程中工作。不太好用。
====================
看看.NET Framework吧,我也是从那上面看到的。搜“Timer 类”可以找到。
Ok, when the time is go to your time you want, please kill the first timer, and set 2nd timer elapsed time 1 hour.
Now, you can process your event every hour at the minute you want.