计时器仅在选定的工作日播放事件

时间:2015-06-08 07:22:15

标签: c# system.timers.timer

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

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

  2. 将在某些特定的周日开始的活动说我只想在周一,周二和周六从给定的StartTime开始。

  3. 将在某些特定月份以及特定周末期间触发的事件表示我希望仅在7月和9月进行,但是在周一,周二和周六的限制日期内从给定的StartTime开始。

  4. 到目前为止我实施的是案例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事件。

2 个答案:

答案 0 :(得分:1)

我倾向于使用Microsoft的Reactive Framework(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

现在你只需要应用过滤器来获得你需要的其他两个可观察量:

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

答案 1 :(得分:0)

最简单的方法是使用最大间隔,以便为您的需求提供最佳准确度(您写的是在一天的特定时间内想要它,所以一小时可能太大但15分钟可能没问题) ,在Timer_Elapsed事件处理程序内部,只需使用DateTime.Now检查条件。

如果DateTime.Now的值符合案例1,请调用将执行案例1的方法。
如果它适合案例2,则调用将执行案例2的方法,
如果它适合案例3,那么,你得到了图片,对吗?