在指定时间执行任务不起作用

时间:2018-04-12 03:32:37

标签: c# task

我知道有很多解决方案可以解决这个问题。我想知道这段代码无效的原因,谢谢。

我正试图在每天的特定时间执行代码。我的代码在这里:

    private static void RunTask(string taskName, int hour, Action act)
    {
        if (hour > 23 || hour < 0)
            throw new ArgumentOutOfRangeException("invalid hour");
        Task.Factory.StartNew(() =>
        {
            var log = new Lazy<Logger>(...);
            while (true)
            {
                try
                {
                    log.Value.LogInfo($"{taskName} running at {hour} clock,{DateTime.Now}");
                    if (DateTime.Now.Hour == hour)
                        act?.Invoke();
                }
                catch (Exception ex)
                {
                    log.Value.LogException(ex);
                }
                Thread.Sleep(new TimeSpan(0, 55, 0));
            }
        });
    }

    ...
    RunTask("task",0,someAction);
    ...

它应该在0时钟执行代码,但它在Windows服务器中不起作用。这是我的日志内容:

  • 任务在0时钟运行,2018 / 4/9 9:35:59
  • 任务在0时钟运行,2018 / 4/9 13:07:08
  • 任务在0时钟运行,2018 / 4/10 19:32:50
  • 任务在0时钟运行,2018 / 4/11 1:36:39
  • 任务在0时钟运行,2018 / 4/11 14:18:07
  • 任务在0时钟运行,2018 / 4/11 14:55:45
  • 任务在0时钟运行,2018 / 4/11 16:01:53

2 个答案:

答案 0 :(得分:1)

您可以使用

https://www.hangfire.io/features.html#recurring-tasks

RecurringJob.AddOrUpdate(() => Console.WriteLine("Recurring!"), Cron.Daily);

您可以使用以下代码在Windows服务中使其工作: http://docs.hangfire.io/en/latest/background-processing/processing-jobs-in-windows-service.html#

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

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

另外你可以:

将它与自托管的.net web api混合,以便有一个很好的用来监控你的任务。

enter image description here

答案 1 :(得分:0)

避免使用Thread.Sleep(new TimeSpan(0, 55, 0));作为阻止你,并且在应用程序中发生线程上下文切换,你的线程可能无法按时发送。

你可以利用计时器每55分钟执行一次动作,如下所示使用计时器

 static void Main()
   {
      Timer timer = new Timer(intvalue); //intvalue equal to 55 min
      timer.Elapsed += async ( sender, e ) => await HandleTimer();
      timer.Start();
      Console.Write("Press any key to exit... ");
      Console.ReadKey();
   }

   private static Task HandleTimer()
   {
     Console.WriteLine("\nHandler not implemented..." );
   }

使用Timer的一个优点是,它每55分钟执行一次,因为它不会等待前一个线程完成,意味着如果前一个任务运行超过55分钟,则下一个任务开火并开始执行它

你可以让线程等待

   Task.Factory.StartNew(async () =>
    {
        while (true)
        {
              //await for 55 min
              await Task.Delay(new TimeSpan(0, 55, 0));
        }
    });

这只是建议可能会有所帮助

相关问题