我应该在哪里开始在 ASP.NET Core 中的持久性后台任务? [英] Where am I supposed to start persistent background tasks in ASP.NET Core?

查看:23
本文介绍了我应该在哪里开始在 ASP.NET Core 中的持久性后台任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Web 应用程序 (ASP.NET Core) 中,我想在后台运行一个作业,该作业正在侦听远程服务器,计算一些结果并将其推送到 Pusher(一个 websocket)上的客户端.

In my web application (ASP.NET Core), I want to run a job in the background that is listening to a remote server, calculating some results and pushing it to the client on Pusher (a websocket).

我不确定我应该从哪里开始这项任务.目前我在结束时开始

I'm not sure where I'm supposed to start this task. Currently I start it at the end of

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)

Startup.cs

但我认为这有问题,在名为Configure"的方法中启动后台作业没有意义.我期待在某处找到一个 Start 方法

but I think there is something wrong about that, it doesn't make sense to start background jobs in a method called "Configure". I was expecting to find a Start method somewhere

此外,当我尝试使用 EF Core 生成初始数据库迁移文件,它实际上执行该方法并启动我的任务..这显然没有任何意义:

Also, when I try to use EF Core to generate initial database migration file, it actually executes that method and starts my tasks.. which clearly doesn't make any sense:

dotnet ef migrations add InitialCreate

从控制台运行它会创建迁移代码,该代码将用于基于我的数据模型在 SQL Server 上创建数据库.

running that from console creates migration code which will be used to create the database on SQL Server based on my data models.

为什么没有一种方法可以让我开始一些任务?我不希望这是一个单独的进程,它真的不需要自己的进程,它本质上是 web 服务器的一部分,因为它确实通过 websocket 与客户端(浏览器)通信,所以这是有道理的将其作为 Web 服务器的一部分运行.

Why isn't there a method where I can start some a Task? I don't want this to be on a separate process, it really doesn't need its own process and it is essentially a part of the web server because it does communicate with the client (browser) via a websocket, so it makes sense to run it as part of the web server.

推荐答案

我相信你正在寻找这个

https://blogs.msdn.microsoft.com/cesardelatorre/2017/11/18/implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x/

我和自己进行了 2 小时自称屡获殊荣的黑客马拉松以学习这一点.

And i did a 2 hour self-proclaimed-award-winning hackathon against myself to learn abit of that.

https://github.com/nikxholas/nautilus

你可以参考这里的注入并从那里实现抽象.

You can refer the injections here and implement the abstracts from there too.

许多 MVC 项目并不是真正需要操作持久性后台任务.这就是为什么您看不到它们通过模板烘焙到新项目中的原因.最好为开发者提供一个可以点击并继续的界面.

Many MVC projects are not really required to operate persistent background tasks. This is why you don't see them baked into a fresh new project via the template. It's better to provide developers an interface to tap on and go ahead with it.

此外,关于为此类后台任务打开套接字连接,我还没有为此建立解决方案.据我所知/做过,我只能向连接到我自己的 socketmanager 的客户端广播有效负载,所以你必须在别处寻找.如果 IHostedService 中的 websockets 有任何问题,我肯定会发出哔哔声.

Also, with regards to opening that socket connection for such background tasks, I have yet to establish a solution for that. As far as I know/did, I was only able to broadcast payload to clients that are connected to my own socketmanager so you'll have to look elsewhere for that. I'll definitely beep if there is anything regarding websockets in an IHostedService.

好吧,这就是发生的事情.

Ok anyway here's what happens.

把它放在你项目的某个地方,它更像是一个界面,让你重载来创建你自己的任务

Put this somewhere in your project, its more of an interface for you to overload with to create your own task

/// Copyright(c) .NET Foundation.Licensed under the Apache License, Version 2.0.
    /// <summary>
    /// Base class for implementing a long running <see cref="IHostedService"/>.
    /// </summary>
    public abstract class BackgroundService : IHostedService, IDisposable
    {
        protected readonly IServiceScopeFactory _scopeFactory;
        private Task _executingTask;
        private readonly CancellationTokenSource _stoppingCts =
                                                       new CancellationTokenSource();

        public BackgroundService(IServiceScopeFactory scopeFactory) {
            _scopeFactory = scopeFactory;
        }

        protected abstract Task ExecuteAsync(CancellationToken stoppingToken);

        public virtual Task StartAsync(CancellationToken cancellationToken)
        {
            // Store the task we're executing
            _executingTask = ExecuteAsync(_stoppingCts.Token);

            // If the task is completed then return it,
            // this will bubble cancellation and failure to the caller
            if (_executingTask.IsCompleted)
            {
                return _executingTask;
            }

            // Otherwise it's running
            return Task.CompletedTask;
        }

        public virtual async Task StopAsync(CancellationToken cancellationToken)
        {
            // Stop called without start
            if (_executingTask == null)
            {
                return;
            }

            try
            {
                // Signal cancellation to the executing method
                _stoppingCts.Cancel();
            }
            finally
            {
                // Wait until the task completes or the stop token triggers
                await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
                                                              cancellationToken));
            }
        }

        public virtual void Dispose()
        {
            _stoppingCts.Cancel();
        }
    }

实际使用方法如下

public class IncomingEthTxService : BackgroundService
    {
        public IncomingEthTxService(IServiceScopeFactory scopeFactory) : base(scopeFactory)
        {
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {

            while (!stoppingToken.IsCancellationRequested)
            {
                using (var scope = _scopeFactory.CreateScope())
                {
                    var dbContext = scope.ServiceProvider.GetRequiredService<NautilusDbContext>();

                    Console.WriteLine("[IncomingEthTxService] Service is Running");

                    // Run something

                    await Task.Delay(5, stoppingToken);
                }
            }
        }
    }

如果你注意到了,这里有一个奖励.您必须使用 servicescope 才能访问数据库操作,因为它是一个单例.

If you noticed, there's a bonus there. You'll have to use a servicescope in order to access db operations because its a singleton.

将您的服务注入

// Background Service Dependencies
            services.AddSingleton<IHostedService, IncomingEthTxService>();

这篇关于我应该在哪里开始在 ASP.NET Core 中的持久性后台任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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