使用异步时,工作服务进程无故停止
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 仍然超出我的理解范围。
我建立了一个非常简单的工作服务项目,只有一个工人(目前)。以下是 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 仍然超出我的理解范围。