如何处理TopShelf中的async Start()错误
本文关键字:async Start 错误 中的 TopShelf 处理 何处理 | 更新日期: 2023-09-27 18:08:22
我有一个TopShelf服务,它使用异步代码连接到web服务和其他应用服务器。
如果在启动时无法初始化连接,服务应该记录一些错误并优雅地停止。
我已经看过这个关于在启动条件不满足时停止TopShelf的问题。这个答案讨论了使用TopShelf HostControl来停止服务。
然而,这个答案依赖于ServiceConfigurator<T>.WhenStarted<T>(Func<T, HostControl, bool> start)
方法。
我目前正在以标准方式配置TopShelf服务:
x.Service<MyService>(s =>
{
s.ConstructUsing(() => new MyService());
s.WhenStarted(s => s.Start());
s.WhenStopped(s => s.Stop());
});
然而我的服务的Start()
方法实际上是async
,定义如下:
public async void Start()
{
await Init();
while (!_canceller.Token.IsCancellationRequested)
{
await Poll();
}
}
这似乎工作良好。但是我在函数的几个地方使用了await关键字。所以,我不能简单地改变我的Start()
方法来接受HostControl
并返回bool
,因为我必须从async
方法返回Task<bool>
。
我目前允许异常从Start()函数冒泡,以便TopShelf可以看到它们并在异常冒泡时自动停止服务。然而,我的代码完全无法处理这些异常,因此,在我写入的各种日志中,我最终得到了令人讨厌的未处理异常错误消息。我更愿意用一个漂亮的错误信息和一个干净的服务关闭来代替。
我有两个问题:
- 使用
async void Start()
方法对TopShelf有任何问题吗? - 是否有一种方法可以使它,如果
Init()
抛出一个异常,异常详细信息被优雅地记录,然后服务停止,假设我的服务运行async
代码?
首先,async void
几乎总是不正确的,除了在一些真正的即发即弃的场景中。你想把它改成async Task
。
有时候你只需要在同步和异步代码的边界处使用.Wait()
。在这种情况下,您可能需要将当前的异步Start()
方法重命名为StartAsync()
,并添加一个Start()
方法来调用它:
public void Start()
{
StartAsync().Wait();
}
public async Task StartAsync()
{
await Init();
while (!_canceller.Token.IsCancellationRequested)
{
await Poll();
}
}
然而,你有另一个问题,在TopShelf的Start()
方法不是"Run"()
方法;也就是说,您应该在服务启动后立即从该方法返回,而不是在服务运行时留在那里。鉴于您已经使用async-await,我可能不会在Start()
中调用Wait()
,而是保存从StartAsync()
返回的Task
,然后当Stop()
被调用时,信号您的Task
停止使用现有的_canceller
,并且只有在Stop()
调用.Wait()
时,留给您这样的东西:
private Task _serviceTask;
public void Start()
{
Init().Wait();
_serviceTask = ExecuteAsync();
}
public void Stop()
{
_canceller.Cancel();
_serviceTask.Wait();
}
public async Task ExecuteAsync()
{
while (!_canceller.Token.IsCancellationRequested)
{
await Poll();
}
}
我应该补充一下,你使用它的方式,你可能在某种程度上摆脱了一些东西,在某种意义上,你的异步Start()
方法将在它到达第一个await
后立即返回TopShelf,但将继续执行。如果你的Stop()
方法调用_canceller.Cancel()
,那么你的异步Start()
方法将在下一次调用Poll()
时终止。
然而,上面的代码更简洁,你必须等到最后一个Poll()
完成执行,这是你以前没有的。您还可以处理异常,如您所提到的。
编辑我还将Init()
调用移到Start()
中,如上所述。