简体   繁体   English

我应该在哪里开始ASP.NET Core中的持久后台任务?

[英]Where am I supposed to start persistent background tasks in ASP.NET Core?

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

in Startup.cs Startup.cs中

but I think there is something wrong about that, it doesn't make sense to start background jobs in a method called "Configure". 但我觉得这有点不对,在一个名为“Configure”的方法中启动后台作业是没有意义的。 I was expecting to find a Start method somewhere 我期待在某个地方找到一个Start方法

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

dotnet ef migrations add InitialCreate

running that from console creates migration code which will be used to create the database on SQL Server based on my data models. 从控制台运行它会创建迁移代码,该代码将用于根据我的数据模型在SQL Server上创建数据库。

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. 我不希望这是一个单独的进程,它实际上不需要自己的进程,它本质上是Web服务器的一部分,因为它确实通过websocket与客户端(浏览器)进行通信,所以它是有道理的将其作为Web服务器的一部分运行。

I believe you're looking for this 我相信你在寻找这个

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

And i did a 2 hour self-proclaimed-award-winning hackathon against myself to learn abit of that. 我做了一个2小时的自我屡获殊荣的黑客马拉松对我自己去学习。

https://github.com/nixxholas/nautilus https://github.com/nixxholas/nautilus

You can refer the injections here and implement the abstracts from there too. 您可以在此处参考注射并从那里实施摘要。

Many MVC projects are not really required to operate persistent background tasks. 许多MVC项目并不是真正需要运行持久性后台任务。 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. 最好为开发人员提供一个界面来点击并继续使用它。

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. 据我所知/做过,我只能将有效负载广播到连接到我自己的socketmanager的客户端,因此你必须在其他地方查找。 I'll definitely beep if there is anything regarding websockets in an IHostedService. 如果在IHostedService中有关于websockets的任何内容,我肯定会发出哔哔声。

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();
        }
    }

Here's how you can actually use it 以下是您实际使用它的方法

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);
                }
            }
        }
    }

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. 您必须使用服务范围才能访问数据库操作,因为它是一个单例。

Inject your service in 注入您的服务

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET Core中托管服务的并行排队后台任务 - Parallel queued background tasks with hosted services in ASP.NET Core 具有托管服务的基于ASP.NET Core事件的后台任务 - ASP.NET Core event based background tasks with hosted services 使用 ASP.Net Core Middleware 启动后台任务 - Start Background Task using ASP.Net Core Middleware 在哪里可以记录 ASP.NET Core 应用程序的启动/停止/错误事件? - Where can I log an ASP.NET Core app's start/stop/error events? 如何使持久性后台任务在 asp.net 核心中发出作用域服务信号? - How to make a persistent background task signal a scoped service in asp.net core? 在asp.net核心中排队任务 - Queuing tasks in asp.net core ASP.NET /调试中的后台任务 - Background Tasks in ASP.NET / Debug 我在 asp.net 核心中的 asp.net 核心标识中面临与线程相关的问题? - I am facing issue thread related issue in asp.net core identity in asp.net core? 在ASP.NET Core RC2应用程序中定期运行后台任务 - Running background tasks periodically in an ASP.NET Core RC2 application asp.net 内核中的配置键是否应该不区分大小写? - Are the configuration keys in asp.net core supposed to be case-insensitive?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM