在自托管 ASP.NET Core 微服务中启动多个后台线程 [英] Start multiple background threads inside Self Hosted ASP.NET Core Microservice

查看:67
本文介绍了在自托管 ASP.NET Core 微服务中启动多个后台线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在哪里可以在Self Hosted Self Contained ASP.NET Core Microservice中创建多个长时间运行的后台线程,其生命周期与微服务生命周期相同?这样从线程中检索到的信息可以作为对请求的响应发送.

Where can i create multiple long running background threads in Self Hosted Self Contained ASP.NET Core Microservice whose lifetime is same as micro-service lifetime? So that information retrieved from threads can be sent as a response to the requests.

尝试了给定的代码,但在后台线程繁忙时会降低 http 请求的性能.Program.cs文件的主要方法是:

Tried given code but it reduces http request performance when background threads are busy. Main method of Program.cs file is:

static void Main(string[] args)
{
    //Start background thread1
    //Start background thread2
    //Around 10 background threads
    //Start host
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseUrls(ServerUrl)
        .UseConfiguration(config)
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .ConfigureServices(s => s.AddRouting())
        .Configure(app => app.UseRouter(r => { (new Router()).Route(r); }))
        .Build();
    host.Run();
}

线程以这种方式工作:

Thread t1 = new Thread(StartWork);
t1.IsBackground = true;
t1.Start();

public void StartWork()
{
    while (ApplicationIsRunning)
    {
        //Get database info >> login into remote devices (SSH) >> get information >> process information >> update application variables and database
        Thread.Sleep(10000);
    }
}

当线程繁忙但http请求性能仍然很差时,CPU利用率仅为1-5%.进入睡眠状态后性能再次提升.

CPU utilization is only 1-5% when threads are busy but still http request performance is very bad. After going to sleep state performance again improves.

问题出在 SSH 客户端连接的连接方法上.在某些时候,connect 方法没有响应,它也会影响所有其他线程.真奇怪!

The issue is at connect method of SSH client connection. At some point connect method is not responding and it affect all other threads also. That is strange!

Renci.SshNet.SshClient sshClient = New Renci.SshNet.SshClient(sshConnectionInfo);
sshClient.Connect();

如果一个线程因为任何原因忙于连接,它不应该影响其他线程.

If one thread is busy in connection because of any reason it should not affect other threads.

推荐答案

代码可能来自 Steve Gordon 在 https://www.stevejgordon.co.uk/asp-net-core-2-ihostedservice ?

code possibly from Steve Gordon's post at https://www.stevejgordon.co.uk/asp-net-core-2-ihostedservice ?

当然可以:)使用 IHostedService(来自 .net 核心的开箱即用),您可以实现以下内容:

sure you can :) With IHostedService (out-of-the-box from .net core) you can implement the following:

public abstract class HostedService : IHostedService
    {

        private Task _executingTask;
        private CancellationTokenSource _cts;

        public Task StartAsync(CancellationToken cancellationToken)
        {
            // Create a linked token so we can trigger cancellation outside of this token's cancellation
            _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

            // Store the task we're executing
            _executingTask = ExecuteAsync(_cts.Token);

            // If the task is completed then return it, otherwise it's running
            return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
        }

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

            // Signal cancellation to the executing method
            _cts.Cancel();

            // Wait until the task completes or the stop token triggers
            await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));

            // Throw if cancellation triggered
            cancellationToken.ThrowIfCancellationRequested();
        }

        // Derived classes should override this and execute a long running method until 
        // cancellation is requested
        protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
    }


then you can implement your abstract class:


public class DataRefreshService : HostedService
{
    private readonly RandomStringProvider _randomStringProvider;

    public DataRefreshService(RandomStringProvider randomStringProvider)
    {
        _randomStringProvider = randomStringProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await _randomStringProvider.UpdateString(cancellationToken);
            await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
        }
    }
}

并且在您的设置中,您只需要添加依赖项:

and in your setup you only have to add the dependency:

services.AddSingleton<IHostedService, DataRefreshService>();

RandomStringProvider 只是一个例子.你得到了图片:)

RandomStringProvider is just an example. You get the picture :)

.net core 自动为您连接,就像一个魅力!非常适合保持rabbitmq 连接打开!

.net core wires this automatically for you, works like a charm! Perfect to keep a rabbitmq-connection open!

试一试!

这篇关于在自托管 ASP.NET Core 微服务中启动多个后台线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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