C# Windows服务未及时启动-是否将初始工作负载传递给计时器?
我正在运行一个Windows服务,它执行一个大型数据迁移过程(第一次运行时需要10分钟以上)。目前,我的服务在启动时运行一次,之后每4小时运行一次。类似这样的内容(节选): 问题是,在部署和运行Windows服务后,Windows服务错误为“服务未及时响应启动或控制请求” 我意识到我可以从OnStart中删除对DoMigration()的初始调用,让服务快速启动——但这样的话,工作将在4小时内无法完成,这是不可取的 我有没有办法为第一个计时器设置一个不同的时间间隔(可能是30秒或60秒),然后再设置一个单独的4小时周期间隔?基本上,我希望将工作负载推出OnStart以防止错误,但我仍然希望在启动后尽快运行它C# Windows服务未及时启动-是否将初始工作负载传递给计时器?,c#,.net,service,timer,windows-services,C#,.net,Service,Timer,Windows Services,我正在运行一个Windows服务,它执行一个大型数据迁移过程(第一次运行时需要10分钟以上)。目前,我的服务在启动时运行一次,之后每4小时运行一次。类似这样的内容(节选): 问题是,在部署和运行Windows服务后,Windows服务错误为“服务未及时响应启动或控制请求” 我意识到我可以从OnStart中删除对DoMigration()的初始调用,让服务快速启动——但这样的话,工作将在4小时内无法完成,这是不可取的 我有没有办法为第一个计时器设置一个不同的时间间隔(可能是30秒或60秒),然后再
这可能吗?这是最好的方法吗?如果您有任何建议,我们将不胜感激。问题是,
OnStart
方法需要在相当短的时间内(也许30秒?)完成,然后Windows才会认为出现了问题。一个简单的解决方案是在第一次运行时快速启动计时器,然后从事件内部重新配置计时器,以便在4小时内再次运行:
protected override void OnStart(string[] args)
{
// Set up timer
int initialIntervalSync = 10; // 10 seconds
timer = new System.Timers.Timer();
timer.Interval = initialIntervalSync * 1000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
timer.Start();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
//Reset timer interval
int intervalSync = 14400; // 4 hours default
timer.Interval = intervalSync * 1000;
this.DoMigration();
}
首先,解决这个问题的最简单方法是使用
async
/wait
:
protected override void OnStart(string[] args)
{
// Storing the returned Task in a variable is a hack
// to suppresses the usual compiler warning.
var _ = DoMigrationLoop();
}
private async Task DoMigrationLoop()
{
while (true)
{
await Task.Run(() => this.DoMigration());
await Task.Delay(TimeSpan.FromHours(4));
}
}
这会导致DoMigration()
方法立即在单独的线程中执行,然后每四小时执行一次。请注意,由于原始的domingrationloop()
方法调用在第一次wait
调用时立即返回,因此OnStart()
方法本身根本没有延迟
可以根据需要随意添加任务取消、异常处理和其他细节。:) 设置另一个间隔几秒钟的计时器进行数据迁移。为什么不使用后台线程进行数据迁移?
protected override void OnStart(string[] args)
{
// Storing the returned Task in a variable is a hack
// to suppresses the usual compiler warning.
var _ = DoMigrationLoop();
}
private async Task DoMigrationLoop()
{
while (true)
{
await Task.Run(() => this.DoMigration());
await Task.Delay(TimeSpan.FromHours(4));
}
}