System.Timers无法正常工作

时间:2016-08-03 08:14:18

标签: c# windows service

嗨,我正在写一个Windows和wpf服务,每天9点在同一时间自动发送电子邮件。 Web服务工作正常,Windows服务每天在我的本地系统中也能正常工作。在服务器系统中它没有在适当的时间工作..

protected override void OnStart(string[] args)
{
    this.WriteToFile("Simple Service started {0}");
    this.ScheduleService();
}

protected override void OnStop()
{
    this.ServicesStop();
    this.WriteToFile("Simple Service stopped {0}");
    this.Schedular.Dispose();
}

private Timer Schedular;

public void ScheduleService()
{
    try
    {
        //Set the Default Time.
        //DateTime scheduledTime = DateTime.MinValue;
        //Get the Scheduled Time from AppSettings.
        DateTime scheduledTime = DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings["ScheduledTime"]);
        WriteToFile("Service entered " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss:FFF tt"));

        TimeSpan timeSpan = scheduledTime.Subtract(DateTime.Now);
        if ((timeSpan.Days < 0 || timeSpan.Hours < 0 || timeSpan.Minutes < 0 || timeSpan.Seconds < 0))
        {
            scheduledTime = scheduledTime.AddDays(1);
            timeSpan = scheduledTime.Subtract(DateTime.Now);
        }

        string schedule = string.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);

        this.WriteToFile("Simple Service scheduled to run after: " + schedule + " {0}");

        //Get the difference in Minutes between the Scheduled and Current Time.
        Int64 dueTime = Convert.ToInt64(timeSpan.TotalMilliseconds);
        this.WriteToFile("dueTime to be fired: " + dueTime + " {0}");
        //Change the Timer's Due Time.
        Schedular = new Timer(dueTime);
        Schedular.Elapsed += new ElapsedEventHandler(Elpaesdtime);
        Schedular.Enabled = true;
    }
    catch (Exception ex)
    {
        WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);

        //Stop the Windows Service.
        using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
        {
            serviceController.Stop();
        }
    }
}

private void Elapsedtime(object sender, System.Timers.ElapsedEventArgs e)
{
    DateTime scheduledTime = DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings["ScheduledTime"]);
    WriteToFile("Service entered " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss:FFF tt"));
    if (DateTime.Now.ToString("MM/dd/yyyy_hh_mm") == scheduledTime.ToString("MM/dd/yyyy_hh_mm"))
    {
        WriteToFile("Service executed " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss:FFF tt"));
        SystemReportServices.ReportServiceClient service = new SystemReportServices.ReportServiceClient();
        service.sendEmailToAdmin();
        service.sendEmailToUser();
        //ExportExcelastDay();
        //If Scheduled Time is passed set Schedule for the next day.
        scheduledTime = scheduledTime.AddDays(1);
    }

    //WriteToFile("Service executed " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss:FFF tt"));

    TimeSpan timeSpan = scheduledTime.Subtract(DateTime.Now);
    if ((timeSpan.Days < 0 || timeSpan.Hours < 0 || timeSpan.Minutes < 0 || timeSpan.Seconds < 0))
    {
        scheduledTime = scheduledTime.AddDays(1);
        timeSpan = scheduledTime.Subtract(DateTime.Now);
    }
    string schedule = string.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);

    this.WriteToFile("Simple Service scheduled to run after: " + schedule + " {0}");

    //Get the difference in Minutes between the Scheduled and Current Time.
    Int64 dueTime = Convert.ToInt64(timeSpan.TotalMilliseconds);
    this.WriteToFile("dueTime to be fired: " + dueTime + " {0}");
    //Change the Timer's Due Time.
    Schedular.Dispose();
    Schedular = new Timer(dueTime);
    Schedular.Elapsed += new ElapsedEventHandler(Elpaesdtime);
    Schedular.Enabled = true;
}

private void SchedularCallback(object e)
{
    this.WriteToFile("Simple Service Log: {0}");
    this.ScheduleService();
}

private void WriteToFile(string text)
{
    string path = @"D:\\SystemReportServicesLog\WindowsServiceLog.txt";
    using (StreamWriter writer = new StreamWriter(path, true))
    {
        writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
        writer.Close();
    }
}

2 个答案:

答案 0 :(得分:1)

根据我的经验,计时器总是很难让他们正确,所以我使用quartz library来处理调度问题。

来自其文档的示例代码,您可以设置触发器以满足您的需求。您可能需要查看更多种类的触发器。

using System;
using System.Threading;

using Quartz;
using Quartz.Impl;
using Quartz.Job;

namespace ConsoleApplication1
{
    public class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                Common.Logging.LogManager.Adapter = new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter {Level = Common.Logging.LogLevel.Info};

                // Grab the Scheduler instance from the Factory 
                IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();

                // and start it off
                scheduler.Start();

                // define the job and tie it to our HelloJob class
                IJobDetail job = JobBuilder.Create<HelloJob>()
                    .WithIdentity("job1", "group1")
                    .Build();

                // Trigger the job to run now, and then repeat every 10 seconds
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity("trigger1", "group1")
                    .StartNow()
                    .WithSimpleSchedule(x => x
                        .WithIntervalInSeconds(10)
                        .RepeatForever())
                    .Build();

                // Tell quartz to schedule the job using our trigger
                scheduler.ScheduleJob(job, trigger);

                // some sleep to show what's happening
                Thread.Sleep(TimeSpan.FromSeconds(60));

                // and last shut down the scheduler when you are ready to close your program
                scheduler.Shutdown();
            }
            catch (SchedulerException se)
            {
                Console.WriteLine(se);
            }

            Console.WriteLine("Press any key to close the application");
            Console.ReadKey();
        }
    }

    public class HelloJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            Console.WriteLine("Greetings from HelloJob!");
        }
    }
}

答案 1 :(得分:0)

以下是Windows服务@Devasish中的Hangfire托管代码。有关在窗口服务中安装hangfire和设置的信息,请参阅此link。使用hangfire,您不再需要担心计时器事件。见下面的例子。

using System.ServiceProcess;
using Hangfire;
using Hangfire.SqlServer;

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        private BackgroundJobServer _server;

        public Service1()
        {
            InitializeComponent();
            GlobalConfiguration.Configuration.UseSqlServerStorage("connection_string");
        }

        protected override void OnStart(string[] args)
        {
            _server = new BackgroundJobServer();

            // It will run everyday at 9:00.
            RecurringJob.AddOrUpdate<EmailService>( emailService => emailService.SendEmail() , "0 9 * * *");
        }

        protected override void OnStop()
        {
            _server.Dispose();
        }
    }
}

public class EmailService
{
    public void SendEmail()
    {
        // code for sending email here
    }
}

如果您不熟悉cron expresion 0 9 * * *的时间安排,可以查看link。我希望这对您有帮助。 :)