aspnet core運行後臺任務

来源:https://www.cnblogs.com/zhiyong-ITNote/archive/2018/11/03/9900830.html
-Advertisement-
Play Games

之前在公司的一個項目中需要用到定時程式,當時使用的是aspnet core提供的IHostedService介面來實現後臺定時程式,具體的示例可去官網查看。現在的dotnet core中預設封裝了實現IHostedService介面的基類BackgroundService,該類實現如下: // Co ...


之前在公司的一個項目中需要用到定時程式,當時使用的是aspnet core提供的IHostedService介面來實現後臺定時程式,具體的示例可去官網查看。現在的dotnet core中預設封裝了實現IHostedService介面的基類BackgroundService,該類實現如下:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Extensions.Hosting
{
    /// <summary>
    /// Base class for implementing a long running <see cref="IHostedService"/>.
    /// </summary>
    public abstract class BackgroundService : IHostedService, IDisposable
    {
        private Task _executingTask;
        private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();

        /// <summary>
        /// This method is called when the <see cref="IHostedService"/> starts. The implementation should return a task that represents
        /// the lifetime of the long running operation(s) being performed.
        /// </summary>
        /// <param name="stoppingToken">Triggered when <see cref="IHostedService.StopAsync(CancellationToken)"/> is called.</param>
        /// <returns>A <see cref="Task"/> that represents the long running operations.</returns>
        protected abstract Task ExecuteAsync(CancellationToken stoppingToken);

        /// <summary>
        /// Triggered when the application host is ready to start the service.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
        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;
        }

        /// <summary>
        /// Triggered when the application host is performing a graceful shutdown.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
        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();
        }
    }
}
View Code

根據BackgroundService源碼,我們只要實現該類的抽象方法ExecuteAsync即可。
可以有兩種實現方式來做定時程式,第一種就是實現一個Timer:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DemoOne.Models
{
    public class TimedBackgroundService : BackgroundService
    {
        private readonly ILogger _logger;
        private Timer _timer;

        public TimedBackgroundService(ILogger<TimedBackgroundService> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
            _logger.LogInformation("周六!");
            return Task.CompletedTask;

            //Console.WriteLine("MyServiceA is starting.");

            //stoppingToken.Register(() => File.Create($"E:\\dotnetCore\\Practice\\Practice\\{DateTime.Now.Millisecond}.txt"));

            //while (!stoppingToken.IsCancellationRequested)
            //{
            //    Console.WriteLine("MyServiceA 開始執行");

            //    await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);

            //    Console.WriteLine("繼續執行");
            //}

            //Console.WriteLine("MyServiceA background task is stopping.");
        }

        private void DoWork(object state)
        {
            _logger.LogInformation($"Hello World! - {DateTime.Now}");
        }

        public override void Dispose()
        {
            base.Dispose();
            _timer?.Dispose();
        }
    }
}
View Code

我們看看StartAsync的源碼。上面的實現方式會直接返回一個已完成的Task,這樣就會直接運行StartAsync方法的if判斷,那麼如果我們不走if呢?那麼就應該由StartAsync方法返回一個已完成的Task.
第二個即是:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DemoOne.Models
{
    public class TimedBackgroundService : BackgroundService
    {
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Console.WriteLine("MyServiceA is starting.");

            stoppingToken.Register(() => File.Create($"E:\\dotnetCore\\Practice\\Practice\\{DateTime.Now.Millisecond}.txt"));

            while (!stoppingToken.IsCancellationRequested)
            {
                Console.WriteLine("MyServiceA 開始執行");

                await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);

                Console.WriteLine("繼續執行");
            }

            Console.WriteLine("MyServiceA background task is stopping.");
        }

        public override void Dispose()
        {
            base.Dispose();
        }
    }
}
View Code

最後我們將實現了BackgroundService的類註入到DI即可:
services.AddHostedService<TimedBackgroundService>();

dotnet core的Microsoft.Extensions.Hosting 組件中,充斥著類似IHostedService介面中定義的方法:StartAsync、StopAsync方法。我們註入的HostedService服務會在WebHost類中通過GetRequiredService獲取到註入的定時服務。隨後執行StartAsync方法開始執行。建議看看Hosting組件源碼,會有很多的收穫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ServerBootstrap與Bootstrap分別是netty中服務端與客戶端的引導類,主要負責服務端與客戶端初始化、配置及啟動引導等工作,接下來我們就通過netty源碼中的示例對ServerBootstrap與Bootstrap的源碼進行一個簡單的分析。首先我們知道這兩個類都繼承自Abstra ...
  • 迴圈是流程式控制制的又一重要結構,“白天-黑夜-白天-黑夜”屬於時間上的迴圈,古人“年復一年、日復一日”的“日出而作、日落而息”便是每天周而複始的生活。電腦程式處理迴圈結構時,給定一段每次都要執行的代碼塊,然後分別指定迴圈的開始條件和結束條件,就形成了常見的迴圈語句。最簡單的迴圈結構只需一個while ...
  • 《PHP核心技術與最佳實踐》是一本致力於為希望成為中高級PHP程式員的讀者提供高效而有針對性指導的經典著作。系統歸納和深刻解讀了PHP開發中的編程思想、底層原理、核心技術、開發技巧、編碼規範和最佳實踐。全書分為5個部分:第一部分(1~2章)從不同的角度闡述了面向對象軟體設計思想的核心概念、技術和原則 ...
  • T1 Adjoin 【問題描述】 定義一種合法的$0 1$串:串中任何一個數字都與$1$相鄰。例如長度為$ 3 的 0 1 $串中,$101$是非法的,因為兩邊的$1$沒有相鄰的$1,011$是合法的,因為三個數都有$1$相鄰。現在問,長度為$N$的$0 1$中有多少是合法的。 【輸入格式】 一行, ...
  • 前言 上一章的靜態天空盒已經可以滿足絕大部分日常使用了。但對於自帶反射/折射屬性的物體來說,它需要依賴天空盒進行繪製,但靜態天空盒並不會記錄周邊的物體,更不用說正在其周圍運動的物體了。因此我們需要在運行期間構建動態天空盒,將周邊物體繪製入當前的動態天空盒。 沒瞭解過靜態天空盒的讀者請先移步到下麵的鏈 ...
  • Mindmanager2016思維導圖 官方原版+永久激活碼+安裝教程 【1】官方原版軟體 (根據自己電腦選擇下載多少位的) ) 百度雲下載地址: 鏈接:https://pan.baidu.com/s/1g-RcTT6AKv4cVMgTklCmQg 提取碼:iqbb 複製這段內容後打開百度網盤手機A ...
  • 1.分析 由於Azure Web AppService平臺的特殊性,所以在C#中原先的config加密方法DataProtectionConfigurationProvider和RSAProtectedConfigurationProvider在Azure平臺上面是無法使用的,會在發佈一段時間後失效 ...
  • ** 溫馨提示:如需轉載本文,請註明內容出處。** 本文鏈接:https://www.cnblogs.com/grom/p/9902098.html 筆者使用了常見的三層架構,Api展示層註入了Swagger,作為開發測試使用的文檔界面,具體搭建教程網上資料很全,不在贅述。 資料庫目前使用了SqlS ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...