.Net核心队列后台任务 [英] .Net Core Queue Background Tasks

查看:198
本文介绍了.Net核心队列后台任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Slender回答了我最初的问题,即在发送HTTP响应后,会发生什么并忘记了,但是现在我剩下的问题是如何正确地将后台任务排入队列

Slender answered my original question about what happens to fire and forget, after the HTTP Response is sent, but Now I'm left with the question how to properly queue background tasks

编辑

众所周知,异步无效通常很糟糕,除了事件处理程序的情况外,我想执行一些后台逻辑而不必等待客户端。我最初的想法是使用Fire and Forget

As we all know Async void is generally bad, except for in the case when it comes to event handlers, I would like to execute some background logic without have to have the client wait. My original Idea was to use Fire and Forget

说我有一个事件:

public event EventHandler LongRunningTask;

然后某人订阅了一次火灾并忘记了任务:

And then someone subscribes a fire and forget task:

LongRunningTask += async(s, e) => { await LongNetworkOperation;};

调用网络api方法:

[HttpGet]
public async IActionResult GetTask()
{
    LongRunningTask?.Invoke(this, EventArgs.Empty);
    return Ok();
}

但是,如果我这样做,我的长期任务就无法保证会完成,如何处理正在运行的后台任务,而又不影响发出请求所花费的时间(例如,我不想等待任务先完成)?

But If I do this my long running task isn't guaranteed to finish, How can I handle running background task without affect the time the time it take to make my request (e.g I don't want to wait for the task to finish first)?

推荐答案

.Net Core 2.1具有IHostedService,它将在后台安全运行任务。我在文档用于 QueuedHostedService ,我已修改为使用BackgroundService。

.Net Core 2.1 Has a IHostedService Which will safely run tasks in the background. I've found an example in the Documentation for QueuedHostedService which I've modied to use the BackgroundService.

public class QueuedHostedService : BackgroundService
{

    private Task _backgroundTask;
    private readonly ILogger _logger;

    public QueuedHostedService(IBackgroundTaskQueue taskQueue, ILoggerFactory loggerFactory)
    {
        TaskQueue = taskQueue;
        _logger = loggerFactory.CreateLogger<QueuedHostedService>();
    }

    public IBackgroundTaskQueue TaskQueue { get; }

    protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (false == stoppingToken.IsCancellationRequested)
        {
            var workItem = await TaskQueue.DequeueAsync(stoppingToken);
            try
            {
                await )workItem(stoppingToken);
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, $"Error occurred executing {nameof(workItem)}.");
            }
        }
    }
}

public interface IBackgroundTaskQueue
{
    void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);

    Task<Func<CancellationToken, Task>> DequeueAsync(
        CancellationToken cancellationToken);
}

public class BackgroundTaskQueue : IBackgroundTaskQueue
{
    private ConcurrentQueue<Func<CancellationToken, Task>> _workItems =
        new ConcurrentQueue<Func<CancellationToken, Task>>();
    private SemaphoreSlim _signal = new SemaphoreSlim(0);

    public void QueueBackgroundWorkItem(
        Func<CancellationToken, Task> workItem)
    {
        if (workItem == null)
        {
            throw new ArgumentNullException(nameof(workItem));
        }

        _workItems.Enqueue(workItem);
        _signal.Release();
    }

    public async Task<Func<CancellationToken, Task>> DequeueAsync(
        CancellationToken cancellationToken)
    {
        await _signal.WaitAsync(cancellationToken);
        _workItems.TryDequeue(out var workItem);

        return workItem;
    }
}

现在我们可以安全地在后台排队任务,而无需影响响应请求的时间。

Now we can safely queue up tasks in the background without affecting the time it takes to respond to a request.

这篇关于.Net核心队列后台任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆