使用异步时,工作服务进程无故停止

Worker service process stops for no apparent reason when using async

我建立了一个非常简单的工作服务项目,只有一个工人(目前)。以下是 ExecuteAsync 方法的完整代码:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
  try
  {
    while (!stoppingToken.IsCancellationRequested)
    {
      _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
      var engine = new CrawlerEngine(_logger);
      try
      {
        await engine.CrawlAsync(stoppingToken);
      }
      catch (Exception ex)
      {
        _logger.LogError(ex.ToString());
      }
      await Task.Delay(TimeSpan.FromMinutes(1));
    }
    _logger.LogInformation("Worker stopping at: {time}", DateTimeOffset.Now);
  }
  catch (Exception ex)
  {
    _logger.LogError(ex.ToString());
  }
}

如您所见,它相当简单,只是一个无限循环,直到取消,其中唯一真正的逻辑都包含在 CrawlerEngine 中。

关键是,如果我 运行 服务,它可能会 运行 几分钟然后退出。它不会记录“工人停止”或异常,它只是简单地停止整个过程。

我尝试更改 CrawlAsync 中的所有异步代码,因此它是完全同步的。这解决了问题,让我感到困惑。

我在 CrawlAsync returns Task 或 Task 中拥有的每个异步方法都在等待。

所以我想也许一些异步代码会抛出一个 try-catch 没有捕获到的异常,但是据我所知,异常应该“冒泡”并被捕获只要你正在使用等待。

我什至添加了一个 AppDomain.UnhandledException 处理程序,它也没有捕获任何内容。

你知道这里到底发生了什么吗?

编辑:为了澄清,我想问一下是否有任何隐藏的异步细节,这会导致它崩溃整个进程而没有多少 try-catch 能够看到它?

编辑 2:似乎使我的进程崩溃的是 WebClient.DownloadStringAsTaskAsync 以及 HttpClient.GetStringAsync。每当我使用其中任何一个时,我的进程都会在某个时候退出。使用同步方法下载字符串不会导致这种情况。

我终于弄清楚退出进程的原因:WhosebugException。

这解释了缺少日志记录等。 我通过将递归方法(称为 HttpClient.GetStringAsync)更改为 for 循环来解决它。

为什么在使用 GetString 的非异步变体时它没有抛出 Whosebug 仍然超出我的理解范围。