只有累積,沒有奇蹟

2023年8月30日 星期三

[NETCore] 如何在 ASP.NET Core 中使用 YAML

前言
今天同事在分享 ASP.NET Core 時介紹使用 YAML 作為組態設定檔,自己在過去比較少接觸 YAML 設定檔,也趁此機會來好好讓彼此熟悉一下,在 YAML 官網介紹說明文字如下
YAML is a human friendly data serialization standard for all programming languages.
YAML 是一種可讀性高,適用於表達資料序列化的格式,在公司 CI\CD 流程中 Docker 以及 Ansible 都有用到 yaml 作為設定檔情境,被越來越多系統使用,YAML 語法在使用上特性區分大小寫,用 空白 縮行做為資料的階層,可以使用 # 作為註解方便人員閱讀,如果有興趣可以閱讀 YAML 语言教程 了解更多關於 YAML 使用方式,使用方式這裡不在多加說明。在 ASP.NET Core 中在預設 Template 專案範本是使用 json 作為設定檔,今天就是要分享的是將 ASP.NET Core 設定檔轉換為 YAML 的方式若有問題歡迎提出一起討論或是給予指導


安裝
在使用前要安裝 YAML 相關的 Library,這裡要介紹的是由微軟 MVP Andrew Lock 所開發 NetEscapades.Configuration,首先先開啟 Nuget Package Manage 輸入 NetEscapades,選擇 NetEscapades.Configuration.Yaml,點選下載
也可以透過 Nuget Package Console 輸入下列指令
Install-Package NetEscapades.Configuration.Yaml -Version 1.6.0
安裝完畢之後到專案檔底下確認是否有安裝成功
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="1.6.0" />
備註 : YAML 官網推薦 ASP.NET 套件為 YamlDotNet、yaml-net、yatools.net,有興趣也可以試試看 

使用方式
接著新增 settings.yml 並設定檔案內容如下,自訂 Account 區段,其中裡面定義 Account 為 Marcus 與 Title 為 This is a book from Yaml config 其組態設定屬性與相對應的值
Account:
  Name: Marcus
  Title: This is a book from Yaml config.
請記得調整 yml 檔案的 copy to output Directory 指定為 copy always 或是 copy if news,避免測試時找不到
並定義 yml 中要對應的類別 Account 屬性 Name 與 Title 
public class Account
{
    public string Name { get; set; }
    public string Title { get; set; }
}
下一步就是告知應用程式啟動時需要一併考慮 settings.yml 檔案內容,修改 progmam.cs 中的 CreateWebHostBuilder 的代碼如下
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(builder =>
        {
            builder.AddYamlFile("settings.yml", optional: true);
        })
        .UseStartup<Startup>();
小提醒 : 在 WebHost.CreateDefaultBuilder 中有定義 BasePath 路徑位置,如果是 console 就需要自己設定 config 路徑

接著調整 Startup 檔案中  ConfigureService  加上以下代碼,指定要取得的內容是從 Account 區段中取得
services.Configure<Account>(Configuration.GetSection("Account"));
這邊使用在 Controller 建構子時注入 IOptions,其型別為 Account 
public Account _account { get; set; }

public ValuesController(IOptions<Account> accountConfig)
{
    _account = accountConfig.Value;
}
接著可以直接在 get 方法使用 Account 類別內容,回傳 name 與 title 的值
[HttpGet]
public ActionResult<string> Get()
{
    return new string[] {_account.Name, _account.Title};
}
最後輸出結果如下,成功的取得 setting.yml 檔案中的內容
使用與取得 appsettings.json 相同,簡單好上手 ! 

同場加映
同事在介紹過程中提到如果不熟悉 yaml 語法的話,可以透過 JSON TO YAML 網站將 json 內容快速轉換為 YAML 格式,如果各位跟我一樣是 YAML 新手的話也可以試試看此網站 : 傳送門,讓寫出來的 YAML 檔案格式更正確,Happy Coding !

參考
Configuration in ASP.NET Core
Creating a custom ConfigurationProvider in ASP.NET Core to parse YAML

2023年8月8日 星期二

[NET] Task.Run 與 Task.Factory.StartNew

前言 
從 .NET 4.0 版本新增 TPL (Task Parallel Library) 函式庫,常在公司專案 Code 中可以看到 Task.Run 與 Task.Factory.StartNew 兩種建立任務的方式,某次同事也有提問對兩者的差異性不太明白,因此這篇文章整理自己對於兩者的相關資訊與用法,希望有不清楚或是自己研究錯誤的地方歡迎提出討論

探索問題
Task.Run 與 Task.Factory.StartNew 使用方式 Sample Code 如下
static void Main(string[] args)
{
    // Task.Factory.StartNew
    Task.Factory.StartNew( () => doSomething());
    
    // Task Run
    Task.Run( () => doSomething() );
}

private static void doSomething()
{
    Console.WriteLine($"Thread Number #{Thread.CurrentThread.ManagedThreadId}");
}
在 .NET 4.0 的時代,可以透過 Task.Factory.StartNew 靜態方法啟用或建立一個新的任務,此靜態方法提供開發者自行定義建立新的 task 任務處理機制,例如控制 TaskScheduler 行為、cancellationToken、creationOptions 等參數,提供相當多的多載方法可依據不同情境使用適合的參數,MSDN 文件也詳細記錄這些參數加上 sample code說明,但反過來看除非知道這些參數的定義與影響程度,使用上很有可能造成使用不正確的狀況發生
在 .NET 4.5 提供了 Task.Run 方法,不需要使用這麼多參數讓開發者在使用上更為方便,實際上 Task.Run 是根據 Task.Factory.StartNew 相同邏輯實現,將 Action 帶入其他參數帶入預設值,舉例來說
Task.Run(doSomething);
可以視為
Task.Factory.StartNew(doSomething,CancellationToken.None,TaskCreationOptions.DenyChildAttach,TaskScheduler.Default);
如果有簡單的任務需求,可以透過 Task.Run 來達成你的需求,使用 Thread Pool 預設的機制來處理新增的 Task 任務 ( TaskScheduler.Default ),也可以說 Task.Run 是 Task.Factory.StartNew 安全參數的縮寫。

Task.Factory.StartNew 使用情境
當 Task.Run 的方法不夠用,或是需求上有更進階的應用情境時可以使用 Task.Factory.StartNew 來完成,看起來很像 PM 說的話,那麼甚麼情境適合用 Task.Factory.StartNew 呢? MSDN 建議有下列情境建議使用  
  • 自訂 TaskCreationOptions : Task.Run 預設的 TaskCreationOptions 參數為 DenyChildAttach,如果需要自訂 TaskCreationOptions 選項時,則需要使用 Task.Factory.StartNew 多載方法
  • 自訂 TaskScheduler : Task.Run 是使用預設的工作排程,如果有需要自訂此參數則不支援,此時也可以透過 Task.Factory.StartNew 達到
舉個例子,某個任務是需要長時間運行的不希望 Task 在完成後 ThreadPool 就立即回收,使用 Task.Run 靜態方法無法實現此需求,也無法定義 TaskCreationOptions 為 LongRunning,此時就需要使用到 Task.Factory.StartNew 指定 creationOptions,範例如下
Task.Factory.StartNew( () => doSomething(), creationOptions:TaskCreationOptions.LongRunning);
如果透過以上簡單案例還是不明白,或許可以再參考另一篇由 微軟 MVP Stephen Cleary 所撰寫的文章 StartNew is Dangerous,文章內容與問題有更多情境與說明,可以在做開發時提供更多的思考方向來決定使用哪種更適合解決當下的問題。

感想
透過以上的說明,希望可以幫助各位了解 Task.Run 與 Task.Factory.StartNew 兩者使用情境與差異,但這只是屬於 Task Parallel Library 的一小部分,近幾年在工作使用上越來越多情境需要用到,日後有時間也會整理更多相關筆記,讓自己對這方面了解更多

參考
Task.Run vs Task.Factory.StartNew
On Task.Factory.StartNew and Task.Run methods
TPL(Task Parallel Language) 
以工作為基礎的非同步程式設計
Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com