ASP.NET Core基礎知識(十一)【Host之Web 主機】

風靈使發表於2019-02-19

概述

.NET 應用配置和啟動主機。 主機負責應用程式啟動和生存期管理。 兩個主機 API 可供使用:

  • Web 主機 – 適用於託管 Web 應用。
  • 通用主機(ASP.NET Core 2.1 或更高版本)– 適用於託管非 Web 應用(例如,執行後臺任務的應用)。
    在未來的版本中,通用主機將適用於託管任何型別的應用,包括 Web 應用。 通用主機最終將取代 Web 主機。

為託管 ASP.NET Core Web 應用,開發人員應使用基於 IWebHostBuilder 的 Web 主機。 為託管非 Web 應用,開發人員應使用基於 HostBuilder 的通用主機。

在 ASP.NET Core 中使用託管服務實現後臺任務

瞭解如何在 ASP.NET Core 中使用託管服務實現後臺任務。

在 ASP.NET Core 中使用承載啟動程式集
瞭解如何使用 IHostingStartup 實現從引用或未引用程式集增強 ASP.NET Core 應用。


ASP.NET Core Web 主機

ASP.NET Core 應用配置和啟動“主機”。 主機負責應用程式啟動和生存期管理。 至少,主機配置伺服器和請求處理管道。 本主題介紹 ASP.NET Core Web 主機 (IWebHostBuilder),它可用於託管 Web 應用。 有關 .NET 通用主機 (IHostBuilder) 的介紹,請參閱 .NET 通用主機

設定主機

建立使用 IWebHostBuilder例項的主機。 通常在應用的入口點來執行 Main 方法。 在專案模板中,Main 位於 Program.cs。 典型的 Program.cs 呼叫 CreateDefaultBuilder以開始設定主機:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

CreateDefaultBuilder 執行下列任務:

  • 使用應用的託管配置提供程式將Kestrel伺服器配置為 Web 伺服器。 有關 Kestrel 伺服器預設選項,請參閱 ASP.NET Core 中的 Kestrel Web 伺服器實現
  • 將內容根設定為由Directory.GetCurrentDirectory返回的路徑。
  • 通過以下物件載入主機配置
    • 字首為 ASPNETCORE_ 的環境變數(例如,ASPNETCORE_ENVIRONMENT)。
    • 命令列引數。
  • 按以下順序載入應用配置:
    • appsettings.json
    • appsettings.{Environment}.json
    • 應用在使用入口程式集的 Development 環境中執行時的機密管理器
    • 環境變數。
    • 命令列引數。
  • 配置控制檯和除錯輸出的日誌記錄。 日誌記錄包含 appsettings.jsonappsettings.{Environment}.json 檔案的日誌記錄配置部分中指定的日誌篩選規則。
  • 使用 ASP.NET Core 模組在 IIS 後面執行時,CreateDefaultBuilder 會啟用 IIS 整合,這會配置應用的基址和埠。 IIS 整合還配置應用以捕獲啟動錯誤。 有關 IIS 預設選項,請參閱 使用 IIS 在 Windows 上託管 ASP.NET Core
  • 如果應用環境為“開發”,請將 ServiceProviderOptions.ValidateScopes設為 true。有關詳細資訊,請參閱作用域驗證

ConfigureAppConfigurationConfigureLogging 以及 IWebHostBuilder的其他方法和擴充套件方法可重寫和增強 CreateDefaultBuilder 定義的配置。 下面是一些示例:

  • ConfigureAppConfiguration用於指定應用的其他 IConfiguration。 下面的 ConfigureAppConfiguration 呼叫新增委託,以在 appsettings.xml 檔案中新增應用配置。 可多次呼叫 ConfigureAppConfiguration。請注意,此配置不適用於主機(例如,伺服器 URL 或環境)。 請參閱主機配置值部分。
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
        })
        ...
  • 下面的 ConfigureLogging 呼叫新增委託,以將最小日誌記錄級別 (SetMinimumLevel) 配置為 LogLevel.Warning。 此設定重寫 CreateDefaultBuilderappsettings.Development.jsonappsettings.Production.json 中配置的設定,分別為 LogLevel.DebugLogLevel.Error。 可多次呼叫 ConfigureLogging
    WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging(logging => 
        {
            logging.SetMinimumLevel(LogLevel.Warning);
        })
        ...
  • 下面呼叫 ConfigureKestrel 來重寫 CreateDefaultBuilder 在配置 Kestrel 時建立的 30,000,000 位元組預設 Limits.MaxRequestBodySize
    WebHost.CreateDefaultBuilder(args)
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.MaxRequestBodySize = 20000000;
        });

內容根確定主機搜尋內容檔案(如 MVC 檢視檔案)的位置。 應用從專案的根資料夾啟動時,會將專案的根資料夾用作內容根。 這是 Visual Studiodotnet new 模板中使用的預設值。

有關應用配置的詳細資訊,請參閱 ASP.NET Core 中的配置

備註
作為使用靜態 CreateDefaultBuilder 方法的替代方法,從WebHostBuilder建立主機是一種受 ASP.NET Core 2.x 支援的方法。 有關詳細資訊,請參閱 ASP.NET Core 1.x 選項卡。

設定主機時,可以提供配置ConfigureServices方法。 如果指定 Startup 類,必須定義 Configure 方法。 有關更多資訊,請參見ASP.NET Core 中的應用啟動。 多次呼叫 ConfigureServices 將追加到另一個。 多次呼叫 WebHostBuilder 上的 ConfigureUseStartup 將替換以前的設定。

主機配置值

WebHostBuilder依賴於以下的方法設定主機配置值:

  • 主機生成器配置,其中包括格式 ASPNETCORE_{configurationKey} 的環境變數。 例如 ASPNETCORE_ENVIRONMENT
  • UseContentRootUseConfiguration等擴充套件(請參閱重寫配置部分)。
  • UseSetting和關聯鍵。 使用 UseSetting 設定值時,該值設定為無論何種型別的字串。

主機使用任何一個選項設定上一個值。 有關詳細資訊,請參閱下一部分中的重寫配置

應用程式鍵(名稱)

在主機構造期間呼叫 UseStartupConfigure時,會自動設定 IHostingEnvironment.ApplicationName屬性。 該值設定為包含應用入口點的程式集的名稱。 要顯式設定值,請使用WebHostDefaults.ApplicationKey

金鑰:applicationName
型別:string
預設值:包含應用入口點的程式集的名稱。
設定使用UseSetting
環境變數ASPNETCORE_APPLICATIONNAME

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")

捕獲啟動錯誤

此設定控制啟動錯誤的捕獲。

:captureStartupErrors
型別:布林型(true1
預設值:預設為 false,除非應用使用 Kestrel 在 IIS 後方執行,其中預設值是 true
設定使用CaptureStartupErrors
環境變數ASPNETCORE_CAPTURESTARTUPERRORS

false 時,啟動期間出錯導致主機退出。 當 true 時,主機在啟動期間捕獲異常並嘗試啟動伺服器。

WebHost.CreateDefaultBuilder(args)
    .CaptureStartupErrors(true)

內容根

此設定確定 ASP.NET Core 開始搜尋內容檔案,如 MVC 檢視等。

:contentRoot
型別:string
預設值:預設為應用程式集所在的資料夾。
設定使用UseContentRoot
環境變數ASPNETCORE_CONTENTROOT

內容根也用作 Web 根設定的基路徑。 如果路徑不存在,主機將無法啟動。

WebHost.CreateDefaultBuilder(args)
    .UseContentRoot("c:\\<content-root>")

詳細錯誤

確定是否應捕獲詳細錯誤。

:detailedErrors
型別:布林型(true1
預設值:false
設定使用UseSetting
環境變數ASPNETCORE_DETAILEDERRORS

啟用(或當環境設定為 Development )時,應用捕獲詳細的異常。

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

環境

設定應用的環境。

:環境
型別:string
預設值:生產
設定使用UseEnvironment
環境變數ASPNETCORE_ENVIRONMENT

環境可以設定為任何值。 框架定義的值包括 Development``StagingProduction。 值不區分大小寫。 預設情況下,從 ASPNETCORE_ENVIRONMENT 環境變數讀取環境。 使用 Visual Studio 時,可能會在 launchSettings.json 檔案中設定環境變數。 有關更多資訊,請參見在 ASP.NET Core 中使用多個環境

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)

承載啟動程式集

設定應用的承載啟動程式集。

:hostingStartupAssemblies
型別:string
預設值:空字串
設定使用UseSetting
環境變數ASPNETCORE_HOSTINGSTARTUPASSEMBLIES

承載啟動程式集的以分號分隔的字串在啟動時載入。

雖然配置值預設為空字串,但是承載啟動程式集會始終包含應用的程式集。 提供承載啟動程式集時,當應用在啟動過程中生成其公用服務時將它們新增到應用的程式集載入。

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

HTTPS 埠

設定 HTTPS 重定向埠。 用於強制實施 HTTPS

鍵:https_port;型別:字串;
預設值:未設定預設值。
設定使用:UseSetting
環境變數:ASPNETCORE_HTTPS_PORT

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080")

承載啟動排除程式集

承載啟動程式集的以分號分隔的字串在啟動時排除。

鍵:hostingStartupExcludeAssemblies
型別:string
預設值:空字串
設定使用UseSetting
環境變數ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

首選承載 URL

指示主機是否應該偵聽使用 WebHostBuilder 配置的 URL,而不是使用 IServer 實現配置的 URL。

:preferHostingUrls
型別:布林型(true1
預設值:true
設定使用PreferHostingUrls
環境變數ASPNETCORE_PREFERHOSTINGURLS

WebHost.CreateDefaultBuilder(args)
    .PreferHostingUrls(false)

阻止承載啟動

阻止承載啟動程式集自動載入,包括應用的程式集所配置的承載啟動程式集。 有關更多資訊,請參見在 ASP.NET Core 中使用承載啟動程式集

:preventHostingStartup
型別:布林型(true1
預設值:false
設定使用UseSetting
環境變數ASPNETCORE_PREVENTHOSTINGSTARTUP

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

伺服器 URL

指示 IP 地址或主機地址,其中包含伺服器應針對請求偵聽的埠和協議。

:urls
型別:string
預設http://localhost:5000
設定使用UseUrls
環境變數ASPNETCORE_URLS

設定為伺服器應響應的以分號分隔 (? 的 URL 字首列表。 例如 http://localhost:123。 使用“*”指示伺服器應針對請求偵聽的使用特定埠和協議(例如 http://*:5000)的 IP 地址或主機名。 協議(http://https://)必須包含每個 URL。 不同的伺服器支援的格式有所不同。

WebHost.CreateDefaultBuilder(args)
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

Kestrel 具有自己的終結點配置 API。 有關更多資訊,請參見ASP.NET Core 中的 Kestrel Web 伺服器實現

關閉超時

指定等待 Web 主機關閉的時長。

:shutdownTimeoutSeconds
型別:int
預設值:5
設定使用UseShutdownTimeout
環境變數ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

雖然鍵使用 UseSetting 接受 int(例如 .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")),但是 UseShutdownTimeout擴充套件方法採用TimeSpan

在超時時間段中,託管:

  • 觸發器IApplicationLifetime.ApplicationStopping
  • 嘗試停止託管服務,對服務停止失敗的任何錯誤進行日誌記錄。

如果在所有託管服務停止之前就達到了超時時間,則會在應用關閉時會終止剩餘的所有活動的服務。 即使沒有完成處理工作,服務也會停止。 如果停止服務需要額外的時間,請增加超時時間。

WebHost.CreateDefaultBuilder(args)
    .UseShutdownTimeout(TimeSpan.FromSeconds(10))

啟動程式集

確定要在其中搜尋 Startup 類的程式集。

:startupAssembly
型別:string
預設值:應用的程式集
設定使用UseStartup
環境變數ASPNETCORE_STARTUPASSEMBLY

按名稱(string)或型別(TStartup)的程式集可以引用。 如果呼叫多個 UseStartup 方法,優先選擇最後一個方法。

WebHost.CreateDefaultBuilder(args)
    .UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
    .UseStartup<TStartup>()

Web 根路徑

設定應用的靜態資產的相對路徑。

:webroot
型別:string
預設值:如果未指定,預設值是“(Content Root)/wwwroot”(如果該路徑存在)。 如果該路徑不存在,則使用無操作檔案提供程式。
設定使用UseWebRoot
環境變數ASPNETCORE_WEBROOT

WebHost.CreateDefaultBuilder(args)
    .UseWebRoot("public")

重寫配置

配置可用於配置 Web 主機。 在下面的示例中,主機配置是根據需要在 hostsettings.json 檔案中指定。 命令列引數可能會重寫從 hostsettings.json 檔案載入的任何配置。 生成的配置(在 config 中)用於通過UseConfiguration配置主機。 IWebHostBuilder 配置會新增到應用配置中,但反之不亦然—ConfigureAppConfiguration 不影響 IWebHostBuilder 配置。

先用 hostsettings.json config 重寫 UseUrls 提供的配置,再用命令列引數 config

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("hostsettings.json", optional: true)
            .AddCommandLine(args)
            .Build();

        return WebHost.CreateDefaultBuilder(args)
            .UseUrls("http://*:5000")
            .UseConfiguration(config)
            .Configure(app =>
            {
                app.Run(context => 
                    context.Response.WriteAsync("Hello, World!"));
            });
    }
}

hostsettings.json:

{
    urls: "http://*:5005"
}

備註
UseConfiguration 擴充套件方法當前不能分析由 GetSection 返回的配置部分(例如 .UseConfiguration(Configuration.GetSection("section"))GetSection 方法將配置鍵篩選到所請求的部分,但將節名稱保留在鍵上(例如 section:urlssection:environment)。 UseConfiguration 方法需要鍵來匹配 WebHostBuilder 鍵(例如 urlsenvironment)。 鍵上存在的節名稱阻止節的值配置主機。 將在即將釋出的版本中解決此問題。 有關詳細資訊和解決方法,請參閱將配置節傳入到 WebHostBuilder.UseConfiguration 使用完整的鍵

UseConfiguration 只將所提供的 IConfiguration 中的金鑰複製到主機生成器配置中。 因此,JSON、INI 和 XML 設定檔案的設定 reloadOnChange: true 沒有任何影響。

若要指定在特定的 URL 上執行的主機,所需的值可以在執行dotnet 執行時從命令提示符傳入。 命令列引數重寫 hostsettings.json 檔案中的 urls 值,且伺服器偵聽埠 8080:

dotnet run --urls "http://*:8080"

管理主機

執行

Run 方法啟動 Web 應用並阻止呼叫執行緒,直到關閉主機:

host.Run();

Start

通過呼叫 Start 方法以非阻止方式執行主機:

using (host)
{
    host.Start();
    Console.ReadLine();
}

如果 URL 列表傳遞給 Start 方法,該列表偵聽指定的 URL:

var urls = new List<string>()
{
    "http://*:5000",
    "http://localhost:5001"
};

var host = new WebHostBuilder()
    .UseKestrel()
    .UseStartup<Startup>()
    .Start(urls.ToArray());

using (host)
{
    Console.ReadLine();
}

應用可以使用通過靜態便捷方法預配置的 CreateDefaultBuilder 預設值初始化並啟動新的主機。 這些方法在沒有控制檯輸出的情況下啟動伺服器,並使用 WaitForShutdown等待中斷(Ctrl-C/SIGINT 或 SIGTERM):

Start(RequestDelegate app)

RequestDelegate 開始:

using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

在瀏覽器中向 http://localhost:5000 發出請求,接收響應“Hello World!” WaitForShutdown 受到阻止,直到發出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 訊息並等待 keypress 退出。

Start(string url, RequestDelegate app)

從 URL 和 RequestDelegate 開始:

using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

生成與 Start(RequestDelegate app) 相同的結果,除非應用在 http://localhost:8080 上響應。

Start(Action<IRouteBuilder> routeBuilder)

使用 IRouteBuilder 的例項 (Microsoft.AspNetCore.Routing) 用於路由中介軟體:

using (var host = WebHost.Start(router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

該示例中使用以下瀏覽器請求:

請求 響應
http://localhost:5000/hello/Martin Hello, Martin!
http://localhost:5000/buenosdias/Catrina Buenos dias, Catrina!
http://localhost:5000/throw/ooops! 使用“ooops!”字串引發異常
http://localhost:5000/throw 使用“Uh oh!”字串引發異常
http://localhost:5000/Sante/Kevin Sante, Kevin!
http://localhost:5000 Hello World!

WaitForShutdown 受到阻止,直到發出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 訊息並等待 keypress 退出。

StartWith(string url, Action<IApplicationBuilder> app)

使用 URL 和 IRouteBuilder 例項:

using (var host = WebHost.Start("http://localhost:8080", router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

生成與 StartWith(Action<IApplicationBuilder> app) 相同的結果,除非應用在 http://localhost:8080 上響應。

StartWith(Action<IApplicationBuilder> app)

提供委託以配置 IApplicationBuilder

using (var host = WebHost.StartWith(app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

在瀏覽器中向 http://localhost:5000 發出請求,接收響應“Hello World!” WaitForShutdown 受到阻止,直到發出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 訊息並等待 keypress 退出。

StartWith(string url, Action<IApplicationBuilder> app)

提供 URL 和委託以配置 IApplicationBuilder

using (var host = WebHost.StartWith("http://localhost:8080", app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

生成與 StartWith(Action<IApplicationBuilder> app) 相同的結果,除非應用在 http://localhost:8080 上響應。

IHostingEnvironment 介面

IHostingEnvironment 介面提供有關應用的 Web 承載環境的資訊。 使用建構函式注入獲取 IHostingEnvironment 以使用其屬性和擴充套件方法:

public class CustomFileReader
{
    private readonly IHostingEnvironment _env;

    public CustomFileReader(IHostingEnvironment env)
    {
        _env = env;
    }

    public string ReadFile(string filePath)
    {
        var fileProvider = _env.WebRootFileProvider;
        // Process the file here
    }
}

基於約定的方法可以用於在啟動時基於環境配置應用。 或者,將 IHostingEnvironment 注入到 Startup 建構函式用於 ConfigureServices

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        HostingEnvironment = env;
    }

    public IHostingEnvironment HostingEnvironment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.IsDevelopment())
        {
            // Development configuration
        }
        else
        {
            // Staging/Production configuration
        }

        var contentRootPath = HostingEnvironment.ContentRootPath;
    }
}

備註
除了 IsDevelopment 擴充套件方法,IHostingEnvironment 提供 IsStagingIsProductionIsEnvironment(string environmentName) 方法。 有關更多資訊,請參見在 ASP.NET Core 中使用多個環境

IHostingEnvironment 服務還可以直接注入到 Configure 方法以設定處理管道:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        // In Development, use the developer exception page
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // In Staging/Production, route exceptions to /error
        app.UseExceptionHandler("/error");
    }

    var contentRootPath = env.ContentRootPath;
}

建立自定義中介軟體時可以將 IHostingEnvironment 注入 Invoke 方法:

public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Configure middleware for Development
    }
    else
    {
        // Configure middleware for Staging/Production
    }

    var contentRootPath = env.ContentRootPath;
}

IApplicationLifetime 介面

IApplicationLifetime允許後啟動和關閉活動。 介面上的三個屬性是用於註冊 Action 方法(用於定義啟動和關閉事件)的取消標記。

取消標記 觸發條件
ApplicationStarted 主機已完全啟動。
ApplicationStopped 主機正在完成正常關閉。 應處理所有請求。 關閉受到阻止,直到完成此事件。
ApplicationStopping 主機正在執行正常關閉。 仍在處理請求。 關閉受到阻止,直到完成此事件。
public class Startup
{
    public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);

        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            appLifetime.StopApplication();
            // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
            eventArgs.Cancel = true;
        };
    }

    private void OnStarted()
    {
        // Perform post-startup activities here
    }

    private void OnStopping()
    {
        // Perform on-stopping activities here
    }

    private void OnStopped()
    {
        // Perform post-stopped activities here
    }
}

StopApplication請求應用終止。 以下類在呼叫類的 Shutdown 方法時使用 StopApplication 正常關閉應用:

public class MyClass
{
    private readonly IApplicationLifetime _appLifetime;

    public MyClass(IApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }

    public void Shutdown()
    {
        _appLifetime.StopApplication();
    }
}

作用域驗證

如果應用環境為“開發”,則CreateDefaultBuilderServiceProviderOptions.ValidateScopes設為 true

若將 ValidateScopes 設為 true,預設服務提供程式會執行檢查來驗證以下內容:

  • 沒有從根服務提供程式直接或間接解析到有作用域的服務。
  • 未將有作用域的服務直接或間接注入到單一例項。

呼叫 BuildServiceProvider 時,會建立根服務提供程式。 在啟動提供程式和應用時,根服務提供程式的生存期對應於應用/服務的生存期,並在關閉應用時釋放。

有作用域的服務由建立它們的容器釋放。 如果作用域建立於根容器,則該服務的生存會有效地提升至單一例項,因為根容器只會在應用/服務關閉時將其釋放。 驗證服務作用域,將在呼叫 BuildServiceProvider 時收集這類情況。

若要始終驗證作用域(包括在生存環境中驗證),請使用主機生成器上的UseDefaultServiceProvider配置ServiceProviderOptions

WebHost.CreateDefaultBuilder(args)
    .UseDefaultServiceProvider((context, options) => {
        options.ValidateScopes = true;
    })

相關文章