1

我在 Windows 服务中使用计时器,这很简单,并且可以在事件结束时将一些数据写入文件。在这个应用程序中,我试图实现 3 种类型的案例:

  1. 事件将每天在同一时间(给定 StartTime)触发。

  2. 将在某些特定工作日触发的事件表示我只想从给定的 StartTime 开始在星期一、星期二和星期六执行此操作。

  3. 将在某些特定月份和那些月份中触发的事件 特定工作日表示我只想在 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 事件。

4

2 回答 2

1

I would be inclined to use Microsoft's Reactive Framework (NuGet "Rx-Main") for this. It would be much simpler.

Here's the hardest part:

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);

This code sets up an observable that will fire first at the time specified in the new TimeSpan(15, 30, 0) and then every day as specified in the TimeSpan.FromDays(1.0). The .Select(n => DateTimeOffset.Now) means that the sequence will return the actual DateTimeOffset that it fired.

Now you just have to apply filters to get the other two observables you need:

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;

They are basically LINQ queries that filter out the events from daily that you don't want to fire.

Then you just need to add the code that actually consumes the events:

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 */
        });

All you need to do to shut down each subscription is to call .Dispose() on them.

于 2015-06-08T10:32:57.077 回答
0

最简单的方法是使用最大的间隔,这将为您的需求提供最佳的准确性(您在一天中的特定时间写下您想要它,所以一个小时可能太大但 15 分钟可能就可以了),并且在里面事件Timer_Elapsed处理程序只需使用 . 检查条件DateTime.Now

如果值DateTime.Now适合情况 1,则调用将执行情况 1 的方法。
如果适合情况 2,则调用将执行情况 2 的方法,
如果适合情况 3,那么,你明白了吗?

于 2015-06-08T07:30:36.253 回答