【问题标题】:c# asp.net core awaiting long running task stops after period of timec# asp.net core等待长时间运行的任务在一段时间后停止
【发布时间】:2021-04-09 20:19:56
【问题描述】:

最近我在 StackOverflow 上问了一个关于 asp.net core 中长时间运行的后台任务的问题。从那时起,我从https://docs.microsoft.com/cs-cz/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio 开始尝试一切,如果我做我所做的,它会在某个时候停止。即使我将它包装在 IServiceProvider.CreateScope 中并等待它,它也会停止。唯一我仍然没有尝试并且我试图避免它的事情是创建专用的.net 应用程序,它只会读取队列并执行它应该做的事情。而且我认为为它创建队列有点矫枉过正,我只想在后台异步运行它,但它只是停止了。抱歉,如果这是一些愚蠢的错误,但这是我的第一个 asp.net 项目,我正在修复这个问题一周。

这是队列版本

public class QueuedHostedService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IBackgroundTaskQueue _queue;
        private readonly ILogger<QueuedHostedService> _logger;

        public QueuedHostedService(IServiceProvider serviceProvider, IBackgroundTaskQueue queue, ILogger<QueuedHostedService> logger)
        {
            _serviceProvider = serviceProvider;
            _queue = queue;
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await BackgroundProcessing(stoppingToken);
        }

        private async Task BackgroundProcessing(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                var workItem = await _queue.DequeueAsync(stoppingToken);

                try
                {
                    var scope = _serviceProvider.CreateScope();
                    var scrapeUrl = scope.ServiceProvider.GetRequiredService<IScopedScrapeUrl>();
                    // The scrape Sound Cloud Task is taking hours
                    await scrapeUrl.ScrapeSoundCloud(workItem);
                }catch(Exception ex)
                {
                    _logger.LogError($"Error occurred executing {nameof(workItem)},\n{ex}");
                }
            }
        }

        public override async Task StopAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Consume Scoped Scrape Url Hosted Service is stopping.");

            await base.StopAsync(stoppingToken);
        }
public class BackgroundScrapeQueue : IBackgroundTaskQueue
    {
        private readonly Channel<Scrape> _queue;
        private readonly ILogger<BackgroundScrapeQueue> _logger;

        public BackgroundScrapeQueue(ILogger<BackgroundScrapeQueue> logger)
        {
            var options = new BoundedChannelOptions(100)
            {
                FullMode = BoundedChannelFullMode.Wait
            };
            _queue = Channel.CreateBounded<Scrape>(options);
            _logger = logger;
        }

        public async ValueTask<Scrape> DequeueAsync(CancellationToken stoppingToken)
        {
            var workItem = await _queue.Reader.ReadAsync(stoppingToken);

            return workItem;
        }

        public async ValueTask QueueBackgroundWorkItemAsync(Scrape scrape)
        {
            if(scrape == null)
            {
                _logger.LogError("Invalid Scrape for queue");
                return;
            }

            await _queue.Writer.WriteAsync(scrape);
        }
    }
    public interface IBackgroundTaskQueue
    {
        ValueTask QueueBackgroundWorkItemAsync(Scrape scrape);

        ValueTask<Scrape> DequeueAsync(CancellationToken stoppingToken);
    }

【问题讨论】:

    标签: c# asp.net-core asynchronous


    【解决方案1】:

    它会在某个时间停止。即使我将它包装在 IServiceProvider.CreateScope 中并等待它,它也会停止。

    是的。这就是内存后台服务的问题。它们可以随时停止,因为它们托管在 ASP.NET 进程中,该进程确定在请求完成时关闭是安全的。 ASP.NET 实际上会请求关闭,然后等待一段时间让服务完成,但还有一个计时器,如果它们在 10 分钟左右没有完成,它们将被强制退出。

    底线是shutdowns are normal。任何假定它可以在 ASP.NET 中无限期运行的代码本质上都是错误的。

    唯一我仍然没有尝试并且我正在努力避免它的事情是创建专门的 .net 应用程序,它只会读取队列并执行它应该做的事情。

    那是only reliable solution

    【讨论】:

    • 好的,但由于某种原因,现在甚至 dotnet 核心应用程序在异步执行这些任务时也会停止。我开始认为你不能永远等待某事,但我看到了一些关于异步的东西,它应该永远等待。
    • “dotnet 核心应用程序”是什么意思?
    • 我创建了不是 asp.net core 而是 .net core 的新应用程序。
    • .net 核心控制台应用程序没有内置任何东西会在一段时间后启动关闭。如果操作是awaited,那么应用程序在完成之前不会退出。
    • 谢谢!我没想到这可能是 PuppeteerSharp 造成的,因为它运行了 200 次没有问题,但现在我发现这可能是以前版本的错误,我没有更新到最新版本。
    猜你喜欢
    • 2017-12-14
    • 2012-05-11
    • 1970-01-01
    • 2014-02-27
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多