gpt4 book ai didi

c# - 如何处理 TopShelf 中的异步 Start() 错误

转载 作者:太空狗 更新时间:2023-10-29 20:04:16 24 4
gpt4 key购买 nike

我有一个使用异步代码连接到网络服务和其他应用程序服务器的 TopShelf 服务。

如果无法在启动时初始化其连接,该服务应记录一些错误并正常停止。

我看过this question关于在不满足启动条件时停止 TopShelf。 This answer讨论使用 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 ,因为我必须返回 Task<bool>来自 async方法。

我目前允许从 Start() 函数中冒出异常,以便 TopShelf 可以看到它们并在异常冒出时自动停止服务。然而,这些异常随后完全没有被我的代码处理,因此我最终在我写入的各种日志中得到了令人讨厌的未处理异常错误消息。我更愿意用一个很好的错误消息和一个干净的服务关闭来代替。

所以,我有两个问题:

  1. 使用 async void Start() 有什么问题吗? TopShelf 的方法?
  2. 有没有办法让如果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"() 方法;也就是说,您应该在服务启动后立即从该方法返回,而不是在服务运行时停留在那里。鉴于您已经在使用异步等待,我可能不会在 Start() 中调用 Wait(),而是保存 TaskStartAsync() 返回,然后在调用 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() 方法会尽快返回到 TopShelf命中第一个 await,但会继续执行。如果您的 Stop() 方法调用 _canceller.Cancel(),那么您的异步 Start() 方法将在下次 Poll() 时终止 被调用。

但是上面的代码更清晰,您必须能够等到最后一个 Poll() 完成执行,而您之前没有这样做。正如您提到的,您还将能够处理异常。

编辑如上所述,我还将 Init() 调用移动到 Start() 中。

关于c# - 如何处理 TopShelf 中的异步 Start() 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39656932/

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