最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

.NET10中的IHostedService深度解析

 更新時間:2026年04月13日 09:21:57   作者:無風聽海  
文章介紹.NET中的IHostedService接口,用于定義由.NET通用主機管理的后臺服務(wù),支持異步啟動和停止操作,提供了生命周期管理和依賴注入等功能,詳細闡述了啟動和停止機制、BackgroundService基類的設(shè)計以及在生產(chǎn)環(huán)境中的使用場景和最佳實踐,感興趣的朋友跟隨小編一起看看吧

一、基本功能介紹

IHostedService是Microsoft.Extensions.Hosting命名空間下的核心接口,用于定義由.NET通用主機管理的后臺服務(wù)。它為在應(yīng)用程序后臺執(zhí)行長時間運行任務(wù)提供了標準化機制,適用于ASP.NET Core Web應(yīng)用、Worker Service應(yīng)用以及任何基于.NET通用主機的應(yīng)用場景。

核心特性

  • 生命周期管理:由主機自動管理服務(wù)的啟動和停止,與應(yīng)用程序生命周期緊密集成
  • 依賴注入支持:可通過構(gòu)造函數(shù)注入所需服務(wù),如日志、配置等
  • 異步友好:基于Task的異步編程模型,支持異步啟動和停止操作
  • 擴展性:可通過實現(xiàn)接口或繼承BackgroundService基類創(chuàng)建自定義后臺服務(wù)

接口定義

public interface IHostedService
{
    // 當應(yīng)用程序主機準備好啟動服務(wù)時觸發(fā)
    Task StartAsync(CancellationToken cancellationToken);
    // 當應(yīng)用程序主機執(zhí)行正常關(guān)閉時觸發(fā)
    Task StopAsync(CancellationToken cancellationToken);
}

二、設(shè)計原理深度剖析

1. 啟動機制(StartAsync)

  • 調(diào)用時機:在應(yīng)用請求處理管道配置完成前、服務(wù)器啟動且IApplicationLifetime.ApplicationStarted觸發(fā)前執(zhí)行
  • 執(zhí)行特性
    • 托管服務(wù)按注冊順序同步執(zhí)行,前一個服務(wù)的StartAsync完成后才會啟動下一個服務(wù)
    • 應(yīng)限制為短期初始化任務(wù),長時間阻塞會延遲應(yīng)用啟動
    • 長期運行邏輯應(yīng)放在單獨的后臺線程或通過BackgroundService的ExecuteAsync方法實現(xiàn)

2. 停止機制(StopAsync)

  • 調(diào)用時機:主機執(zhí)行正常關(guān)閉時觸發(fā),意外關(guān)閉(如進程崩潰)可能不會調(diào)用
  • 取消令牌:默認有30秒超時(可通過ShutdownTimeout配置修改),超時后主機將強制關(guān)閉服務(wù)
  • 執(zhí)行要求
    • 應(yīng)立即停止后臺操作并釋放資源
    • 取消令牌觸發(fā)后,應(yīng)及時返回,不阻塞主機關(guān)閉流程
    • 實現(xiàn)IDisposable或IAsyncDisposable接口以確保非托管資源正確釋放

3. BackgroundService基類設(shè)計

BackgroundService是IHostedService的抽象基類,簡化了長時間運行服務(wù)的實現(xiàn):

  • 核心方法protected abstract Task ExecuteAsync(CancellationToken stoppingToken),表示服務(wù)的整個生命周期
  • 執(zhí)行流程
    1. StartAsync調(diào)用后啟動ExecuteAsync,返回一個表示服務(wù)生存期的Task
    2. 直到ExecuteAsync變?yōu)楫惒剑ㄍㄟ^await)才會啟動其他服務(wù)
    3. StopAsync觸發(fā)時,取消令牌會被激活,應(yīng)立即完成ExecuteAsync執(zhí)行
    4. 主機在StopAsync中會等待ExecuteAsync完成

4. 服務(wù)注冊與激活

  • 注冊方式:通過AddHostedService<THostedService>擴展方法注冊,服務(wù)默認是單例生命周期
    services.AddHostedService<TimedHostedService>();
  • 激活時機:應(yīng)用啟動時激活一次,應(yīng)用關(guān)閉時正常關(guān)閉
  • 錯誤處理:執(zhí)行后臺任務(wù)期間引發(fā)錯誤時,即使未調(diào)用Dispose,也會調(diào)用StopAsync

三、生產(chǎn)環(huán)境使用場景與實現(xiàn)示例

場景1:定時執(zhí)行任務(wù)(計時器服務(wù))

適用于需要按固定間隔執(zhí)行的任務(wù),如數(shù)據(jù)同步、緩存清理等。

public class TimedHostedService : IHostedService, IDisposable
{
    private int executionCount = 0;
    private readonly ILogger<TimedHostedService> _logger;
    private Timer? _timer = null;
    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }
    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");
        // 立即啟動,每5秒執(zhí)行一次
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
        return Task.CompletedTask;
    }
    private void DoWork(object? state)
    {
        var count = Interlocked.Increment(ref executionCount);
        _logger.LogInformation("Timed Hosted Service is working. Count: {Count}", count);
    }
    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");
        _timer?.Change(Timeout.Infinite, 0); // 禁用計時器
        return Task.CompletedTask;
    }
    public void Dispose()
    {
        _timer?.Dispose(); // 釋放計時器資源
    }
}

注意:Timer不等待先前的DoWork執(zhí)行完成,如需確保任務(wù)串行執(zhí)行,應(yīng)使用其他同步機制。

場景2:使用有作用域的服務(wù)

托管服務(wù)默認是單例,無法直接注入有作用域的服務(wù)(如DbContext),需創(chuàng)建服務(wù)作用域。

// 有作用域的服務(wù)
internal interface IScopedProcessingService
{
    Task DoWork(CancellationToken stoppingToken);
}
internal class ScopedProcessingService : IScopedProcessingService
{
    private int executionCount = 0;
    private readonly ILogger<ScopedProcessingService> _logger;
    public ScopedProcessingService(ILogger<ScopedProcessingService> logger)
    {
        _logger = logger;
    }
    public async Task DoWork(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            executionCount++;
            _logger.LogInformation("Scoped Processing Service is working. Count: {Count}", executionCount);
            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }
}
// 托管服務(wù)
public class ConsumeScopedServiceHostedService : BackgroundService
{
    private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
    private readonly IServiceProvider _services;
    public ConsumeScopedServiceHostedService(IServiceProvider services, 
        ILogger<ConsumeScopedServiceHostedService> logger)
    {
        _services = services;
        _logger = logger;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Consume Scoped Service Hosted Service running.");
        await DoWork(stoppingToken);
    }
    private async Task DoWork(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Consume Scoped Service Hosted Service is working.");
        // 創(chuàng)建服務(wù)作用域
        using (var scope = _services.CreateScope())
        {
            var scopedProcessingService = 
                scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
            await scopedProcessingService.DoWork(stoppingToken);
        }
    }
    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Consume Scoped Service Hosted Service is stopping.");
        await base.StopAsync(stoppingToken);
    }
}
// 注冊服務(wù)
services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<IScopedProcessingService, ScopedProcessingService>();

場景3:隊列后臺任務(wù)

適用于處理異步任務(wù)隊列,如用戶請求觸發(fā)的后臺處理、批量操作等。

// 任務(wù)隊列接口
public interface IBackgroundTaskQueue
{
    ValueTask QueueBackgroundWorkItemAsync(Func<CancellationToken, ValueTask> workItem);
    ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(CancellationToken cancellationToken);
}
// 任務(wù)隊列實現(xiàn)
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
    private readonly Queue<Func<CancellationToken, ValueTask>> _workItems = new();
    private readonly SemaphoreSlim _signal = new(0);
    public async ValueTask QueueBackgroundWorkItemAsync(Func<CancellationToken, ValueTask> workItem)
    {
        if (workItem == null)
            throw new ArgumentNullException(nameof(workItem));
        _workItems.Enqueue(workItem);
        _signal.Release(); // 通知隊列有新任務(wù)
    }
    public async ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(CancellationToken cancellationToken)
    {
        await _signal.WaitAsync(cancellationToken); // 等待任務(wù)
        return _workItems.Dequeue();
    }
}
// 隊列托管服務(wù)
public class QueuedHostedService : BackgroundService
{
    private readonly ILogger<QueuedHostedService> _logger;
    private readonly IBackgroundTaskQueue _taskQueue;
    public QueuedHostedService(IBackgroundTaskQueue taskQueue, 
        ILogger<QueuedHostedService> logger)
    {
        _taskQueue = taskQueue;
        _logger = logger;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Queued Hosted Service is running.");
        await BackgroundProcessing(stoppingToken);
    }
    private async Task BackgroundProcessing(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // 從隊列獲取任務(wù)
            var workItem = await _taskQueue.DequeueAsync(stoppingToken);
            try
            {
                await workItem(stoppingToken); // 執(zhí)行任務(wù)
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occurred executing work item.");
            }
        }
    }
    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Queued Hosted Service is stopping.");
        await base.StopAsync(stoppingToken);
    }
}
// 注冊服務(wù)
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
services.AddHostedService<QueuedHostedService>();

四、最佳實踐與注意事項

1. 避免長時間阻塞StartAsync

  • 啟動時的長時間操作應(yīng)移至后臺線程或ExecuteAsync方法
  • 可使用Task.Run啟動后臺任務(wù),避免阻塞主線程

2. 正確處理取消令牌

  • 在所有異步操作中傳遞stoppingToken,確保及時響應(yīng)關(guān)閉信號
  • 定期檢查令牌的IsCancellationRequested屬性,必要時拋出OperationCanceledException

3. 資源管理

  • 實現(xiàn)IDisposable/IAsyncDisposable接口,確保釋放所有非托管資源
  • 在StopAsync中停止計時器、網(wǎng)絡(luò)連接等資源密集型操作

4. 錯誤處理與日志

  • 在后臺任務(wù)中捕獲并記錄異常,避免應(yīng)用崩潰
  • 使用ILogger記錄服務(wù)啟動、停止和執(zhí)行狀態(tài),便于問題排查

5. 服務(wù)注冊順序

  • 托管服務(wù)按注冊順序啟動,按相反順序停止
  • 依賴其他服務(wù)的托管服務(wù)應(yīng)在依賴服務(wù)之后注冊

6. 作用域管理

  • 單例托管服務(wù)中使用有作用域服務(wù)時,必須創(chuàng)建新的服務(wù)作用域
  • 避免在單例服務(wù)中直接注入DbContext等有作用域服務(wù)

五、與其他后臺處理方案對比

特性IHostedServiceHangfire/QuartzAzure WebJobs
集成度與.NET通用主機深度集成獨立庫,需額外配置Azure特有,與應(yīng)用服務(wù)集成
持久性內(nèi)存中,重啟后丟失支持持久化存儲支持持久化隊列
調(diào)度功能基礎(chǔ)定時功能復雜調(diào)度( cron 表達式)靈活觸發(fā)機制
部署復雜性低,無額外依賴中,需配置存儲高,依賴Azure服務(wù)
適用場景輕量級后臺任務(wù)復雜調(diào)度任務(wù)Azure云原生應(yīng)用

六、總結(jié)

IHostedService為.NET應(yīng)用提供了統(tǒng)一的后臺任務(wù)管理機制,通過與通用主機的集成,簡化了長時間運行服務(wù)的開發(fā)和部署流程。無論是簡單的定時任務(wù)、需要作用域服務(wù)的后臺處理,還是復雜的隊列任務(wù)處理,都可以通過實現(xiàn)IHostedService接口或繼承BackgroundService基類來實現(xiàn)。

關(guān)鍵要點:

  1. 遵循主機生命周期,正確實現(xiàn)StartAsync和StopAsync方法
  2. 避免在StartAsync中執(zhí)行長時間阻塞操作
  3. 正確處理取消令牌,確保服務(wù)能夠及時響應(yīng)關(guān)閉信號
  4. 實現(xiàn)IDisposable接口釋放非托管資源
  5. 在單例服務(wù)中使用有作用域服務(wù)時,創(chuàng)建新的服務(wù)作用域

到此這篇關(guān)于.NET10中的IHostedService深度解析的文章就介紹到這了,更多相關(guān).net ihostedService內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

齐齐哈尔市| 卓尼县| 易门县| 阿图什市| 石嘴山市| 礼泉县| 常熟市| 麻阳| 芦山县| 团风县| 和田县| 磐石市| 德保县| 宣武区| 桃源县| 汉中市| 永仁县| 贵南县| 温泉县| 南平市| 彭泽县| 蒲城县| 三亚市| 湘潭县| 修文县| 芦溪县| 屏东市| 普定县| 芦山县| 宜昌市| 卓资县| 罗田县| 娄烦县| 清丰县| 平谷区| 南平市| 吴旗县| 常山县| 禄劝| 万荣县| 武陟县|