Windows 服务没有及时启动 - 将初始工作量传递给计时器?
Windows Service not starting in a timely manner - pass off initial workload to timer?
我正在 运行 宁 Windows 服务执行大型数据迁移过程(第一次 运行 需要 10 分钟以上)。目前我有服务 运行ning 最初在启动时一次,然后每 4 小时一次。像这样(摘录):
protected override void OnStart(string[] args)
{
// Set up timer
int intervalSync = 14400; // 4 hours default
timer = new System.Timers.Timer();
timer.Interval = intervalSync * 1000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
timer.Start();
// Call once initially.
this.DoMigration();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
this.DoMigration();
}
问题是在部署和 运行ning 之后,Windows 服务错误 "The service did not respond to the start or control request in a timely fashion"。
我意识到我可以只从 OnStart 中删除对 DoMigration() 的初始调用,并让服务快速启动 - 但是工作将在 4 小时内无法完成,这是不可取的。
有没有办法可以将第一个计时器的时间间隔设置为 运行(可能是 30 秒或 60 秒),然后再设置单独的 4 小时周期性间隔?基本上我想将工作负载推出 OnStart 以防止错误,但我仍然希望在启动后尽快拥有它 运行。
这可能吗?这是最好的方法吗?如有任何建议,我们将不胜感激。
问题是 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
/await
:
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()
方法立即在单独的线程中执行,此后每四个小时执行一次。请注意,由于原始 DoMigrationLoop()
方法在第一次 await
调用时立即调用 returns,因此 OnStart()
方法本身根本没有延迟。
随意添加任务取消、异常处理和其他需要的细节。 :)
我正在 运行 宁 Windows 服务执行大型数据迁移过程(第一次 运行 需要 10 分钟以上)。目前我有服务 运行ning 最初在启动时一次,然后每 4 小时一次。像这样(摘录):
protected override void OnStart(string[] args)
{
// Set up timer
int intervalSync = 14400; // 4 hours default
timer = new System.Timers.Timer();
timer.Interval = intervalSync * 1000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
timer.Start();
// Call once initially.
this.DoMigration();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
this.DoMigration();
}
问题是在部署和 运行ning 之后,Windows 服务错误 "The service did not respond to the start or control request in a timely fashion"。
我意识到我可以只从 OnStart 中删除对 DoMigration() 的初始调用,并让服务快速启动 - 但是工作将在 4 小时内无法完成,这是不可取的。
有没有办法可以将第一个计时器的时间间隔设置为 运行(可能是 30 秒或 60 秒),然后再设置单独的 4 小时周期性间隔?基本上我想将工作负载推出 OnStart 以防止错误,但我仍然希望在启动后尽快拥有它 运行。
这可能吗?这是最好的方法吗?如有任何建议,我们将不胜感激。
问题是 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
/await
:
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()
方法立即在单独的线程中执行,此后每四个小时执行一次。请注意,由于原始 DoMigrationLoop()
方法在第一次 await
调用时立即调用 returns,因此 OnStart()
方法本身根本没有延迟。
随意添加任务取消、异常处理和其他需要的细节。 :)