Timers Elapsed 事件仅在选定的工作日
Posted
技术标签:
【中文标题】Timers Elapsed 事件仅在选定的工作日【英文标题】:Timers Elapsed event only on selected weekdays 【发布时间】:2015-08-22 13:44:30 【问题描述】:我在 Windows 服务中使用计时器,这很简单,并且可以在事件结束时将一些数据写入文件。在这个应用程序中,我尝试实现 3 种类型的案例:
事件将在每天的同一时间(给定 StartTime)触发。
将在某些特定工作日触发的事件表示我只想从给定的 StartTime 开始在星期一、星期二和星期六执行此操作。
将在某些特定月份和这些月份触发的事件 特定工作日表示我只想在 7 月和 9 月执行此操作,但从给定的 StartTime 开始在周一、周二和周六的受限日子。
到目前为止,我实施的是案例 1,我不确定如何为案例 2 和案例 3 做同样的事情。(我认为的逻辑很奇怪)。如果我在解决案例 2 中得到一些帮助,也将有助于实施案例 3。欢迎任何其他建议。
这是我的代码:
private static Timer aTimer;
public static void Main()
aTimer = new System.Timers.Timer(2000);
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
String path = @"E:\sample1.txt";
StreamWriter osw = new StreamWriter(path, true);
Console.WriteLine("Enter the case (1 or 2 or 3)");
var ch = int.Parse(Console.ReadLine());
//throw new NotImplementedException();
switch (ch)
default: break;
case 1:aTimer = new System.Timers.Timer();
aTimer.Elapsed += OnTimedEventCase1;
aTimer.Enabled = false;
break;
case 2: aTimer = new System.Timers.Timer();
aTimer.Elapsed += OnTimedEventCase2;
aTimer.Enabled = false;
break;
case 3: aTimer = new System.Timers.Timer();
aTimer.Elapsed += OnTimedEventCase3;
aTimer.Enabled = false;
break;
osw.Close();
osw = null;
// Elapsed Event for Case 1
private void OnTimedEventCase1(object source, ElapsedEventArgs e)
//throw new NotImplementedException();
Console.WriteLine("Daily Job");
Console.WriteLine("DateTime: " + DateTime.Now);
Timer theTimer = (System.Timers.Timer)source;
theTimer.Interval = 1000 * 24 * 60 * 60; // will do it daily i.e, 24 hours
theTimer.Enabled = true;
// Elapsed Event for Case 2
private void OnTimedEventCase2(object source, ElapsedEventArgs e)
// throw new NotImplementedException();
string[] days = new string[]"Monday", "Tuesday" ,"Saturday";
Console.WriteLine("WeekDays Job");
Console.WriteLine("DateTime: " + DateTime.Now);
Timer theTimer = (System.Timers.Timer)source;
//theTimer.Interval = I don't know how to fire event here according weekdays
//theTimer.Enabled = true;
// Elapsed Event for Case 3
private void OnTimedEventCase3(object source, ElapsedEventArgs e)
// throw new NotImplementedException();
string[] days = new string[]"Monday", "Tuesday" ,"Saturday";
string[] months= new string[]"July", "September";
Console.WriteLine("Monthly job");
Console.WriteLine("DateTime: " + DateTime.Now);
Timer theTimer = (System.Timers.Timer)source;
//theTimer.Interval = I don't know how to fire event here according months and then weekdays
//theTimer.Enabled = true;
虽然我可以轻松地实现几个小时甚至 1 天的经过事件,这是我需要通过 timeInterval 属性的恒定时间,但是在这里我没有得到如何为选定的工作日和选定的月份触发 Elapsed 事件。
【问题讨论】:
var arr = new List<string> "Monday", "Wednesday", "Friday" ; if (arr.Contains(DateTime.Today.DayOfWeek.ToString())) _timer.Elapsed += _timer_elaspsed;
这样的?
谢谢阿米特 我猜这个答案会解决的。
让我们知道会发生什么。
是的,我正在努力
【参考方案1】:
我倾向于为此使用 Microsoft 的响应式框架 (NuGet "Rx-Main")。会简单很多。
这是最难的部分:
IObservable<DateTimeOffset> daily =
Observable
.Create<long>(o =>
var startTime = DateTimeOffset.Now.Date.Add(new TimeSpan(15, 30, 0));
if (startTime < DateTimeOffset.Now)
startTime = startTime.AddDays(1.0);
return Observable.Timer(startTime, TimeSpan.FromDays(1.0)).Subscribe(o);
)
.Select(n => DateTimeOffset.Now);
此代码设置了一个 observable,它将首先在new TimeSpan(15, 30, 0)
中指定的时间触发,然后在TimeSpan.FromDays(1.0)
中指定的每一天触发。 .Select(n => DateTimeOffset.Now)
表示序列将返回它触发的实际 DateTimeOffset
。
现在你只需要应用过滤器来获得你需要的另外两个 observable:
IObservable<DateTimeOffset> weekday =
from n in daily
where new []
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Saturday,
.Contains(n.DayOfWeek)
select n;
IObservable<DateTimeOffset> monthWeekday =
from n in weekday
where new [] 7, 9, .Contains(n.Month)
select n;
它们基本上是 LINQ 查询,用于从 daily
中过滤掉您不想触发的事件。
那么你只需要添加实际消费事件的代码:
IDisposable dailySubscription =
daily
.Subscribe(n =>
/* daily work goes here */
);
IDisposable weekdaySubscription =
weekday
.Subscribe(n =>
/* weekday work goes here */
);
IDisposable monthWeekdaySubscription =
monthWeekday
.Subscribe(n =>
/* month/weekday work goes here */
);
要关闭每个订阅,您只需调用 .Dispose()
即可。
【讨论】:
我很欣赏你的回答,但如果开始做一些新的事情,这将需要很多时间,因为我需要阅读“Rx-Main”的文档,我可能不会不想那样做。因为我确实有一个符合该条件的逻辑,因为我只需要计算一些东西就可以得到解决方案,但我认为这不是最佳的,因此我正在等待正确的答案。【参考方案2】:最简单的方法是使用最大的间隔来满足您的需求(您在一天中的特定时间写下您想要它,所以一个小时可能太大,但 15 分钟可能就可以了) ,在Timer_Elapsed
事件处理程序中,只需使用DateTime.Now
检查条件。
如果DateTime.Now
的值适合案例 1,则调用将执行案例 1 的方法。
如果适合案例 2,请调用将执行案例 2 的方法,
如果它适合第 3 种情况,那么,你明白了吧?
【讨论】:
以上是关于Timers Elapsed 事件仅在选定的工作日的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在 Timer 被处理后生成触发 System.Timers.Timer 的 Elapsed 事件的示例?
如何防止 System.Timers.Timer 在线程池上排队执行?