【发布时间】: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