gpt4 book ai didi

c# - 在应用程序/服务关闭/停止之前等待计时器经过事件完成

转载 作者:可可西里 更新时间:2023-11-01 08:45:15 24 4
gpt4 key购买 nike

总结:在 Windows 服务和控制台应用程序中,我调用了一个包含计时器的公共(public)库,该计时器会定期触发大约需要 30 秒才能完成的操作。这工作正常,但是......

当调用服务停止或应用程序退出并且计时器在 ElapsedEventHandler 中时,我需要服务停止/应用程序退出以等待事件处理程序完成。

我通过在调用计时器停止方法时检查 bool InEvent 属性来实现此功能。

虽然这很实用,但问题是:这是执行此操作的最佳方法吗?是否有替代方法可以更好地满足此目的?

另一个问题是我需要避免服务停止请求因“服务无法响应停止请求”而失败

这是我的实现

public sealed class TimedProcess : IDisposable
{
static TimedProcess singletonInstance;
bool InEvent;
Timer processTimer;

private TimedProcess()
{
}

public static TimedProcess Instance
{
get
{
if (singletonInstance == null)
{
singletonInstance = new TimedProcess();
}

return singletonInstance;
}
}

public void Start(double interval)
{
this.processTimer = new Timer();
this.processTimer.AutoReset = false;
this.processTimer.Interval = interval;
this.processTimer.Elapsed += new ElapsedEventHandler(this.processTimer_Elapsed);
this.processTimer.Enabled = true;
}

public void Stop()
{
if (processTimer != null)
{
while (InEvent)
{
}

processTimer.Stop();
}
}

void processTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
InEvent = true;
// Do something here that takes ~30 seconds
}
catch
{
}
finally
{
InEvent = false;
processTimer.Enabled = true;
}
}

public void Dispose()
{
if (processTimer != null)
{
Stop();
processTimer.Dispose();
}
}
}

这就是它在服务 OnStart/控制台应用程序 main 中的调用方式:

TimedProcess.Instance.Start(1000);

这是在 service OnStop 和 application main(等待按键)中的调用方式:

TimedProcess.Instance.Stop();

最佳答案

可能最简单和最可靠的方法是使用 Monitor。创建一个主程序和定时器回调可以访问的对象:

private object _timerLock = new object();

你的主程序试图在关闭之前锁定它:

// wait for timer process to stop
Monitor.Enter(_timerLock);
// do shutdown tasks here

并且您的计时器回调也将其锁定:

void processTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!Monitor.TryEnter(_timerLock))
{
// something has the lock. Probably shutting down.
return;
}
try
{
// Do something here that takes ~30 seconds
}
finally
{
Monitor.Exit(_timerLock);
}
}

主程序一旦获得锁就永远不应该释放。

如果你想让主程序在一段时间后继续运行并关闭,不管它是否获得了锁,使用Monitor.TryEnter。例如,这将等待 15 秒。

bool gotLock = Monitor.TryEnter(_timerLock, TimeSpan.FromSeconds(15));

如果能够获得锁,则返回值为true

顺便说一下,我强烈建议您使用 System.Threading.Timer 而不是 System.Timers.Timer。后者压制异常,最终可能会隐藏错误。如果在您的 Elapsed 事件中发生异常,它将永远不会逃脱,这意味着您永远不会知道它。看我的blog post获取更多信息。

关于c# - 在应用程序/服务关闭/停止之前等待计时器经过事件完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7043012/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com