我知道有很多解决方案可以解决这个问题。我想知道这段代码无效的原因,谢谢。
我正试图在每天的特定时间执行代码。我的代码在这里:
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 :(得分: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混合,以便有一个很好的用来监控你的任务。
答案 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));
}
});
这只是建议可能会有所帮助