Skip to main content
 首页 » 编程设计

c#之在自托管 ASP.NET Core 微服务中启动多个后台线程

2024年01月21日26qq78292959

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

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

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%。进入休眠状态后,性能再次提高。

问题在于 SSH 客户端连接的连接方法。在某些时候,connect 方法没有响应,它也会影响所有其他线程。这很奇怪!
Renci.SshNet.SshClient sshClient = New Renci.SshNet.SshClient(sshConnectionInfo); 
sshClient.Connect(); 

如果一个线程由于任何原因忙于连接,则不应影响其他线程。

请您参考如下方法:

编辑:代码可能来自史蒂夫戈登的帖子 https://www.stevejgordon.co.uk/asp-net-core-2-ihostedservice ?

你当然可以 :)
使用 IHostedService(来自 .net core 的开箱即用),您可以实现以下功能:

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

在您的设置中,您只需要添加依赖项:
services.AddSingleton<IHostedService, DataRefreshService>(); 
RandomStringProvider只是一个例子。你得到了图片:)

.net 核心线这会自动为您服务,就像一个魅力!完美保持rabbitmq-connection打开!

试一试!