只有累積,沒有奇蹟

2019年9月13日 星期五

[VisualStudio] ASP.NET Core 非同步代碼分析工具 - Threading.Analyzers

前言
在上一篇介紹了 ASP.NET Core Task block 檢測器 - Ben.BlockingDetector ,可以在 ASP.NET Runtime 時偵測 task block 的情境並透過 log 輸出,但預防的工作總是希望越早進行越好,越快發現就更早的預防不好的寫法及早修改,本篇要介紹的是非同步代碼分析套件,可以分析靜態代碼中可能用法"不正確"的代碼,可以若有問題或是錯誤的地方歡迎高手大大給予指導或討論

安裝
開啟 Visual Studio 的 Nuget 搜尋 Microsoft.VisualStudio.Threading.Analyzers 找到後下載
或是可以透過 Nuget Package Console 輸入下列指令
  1. Install-Package Microsoft.VisualStudio.Threading.Analyzers -Version 16.3.52
安裝完畢之後到專案檔底下確認是否有安裝成功
  1. <ItemGroup>
  2. <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.3.52" />
  3. </ItemGroup>

分析指南
在安裝完後會針對目前專案靜態代碼進行分析,主要目的是透過此套件來檢查有關 Threads 和非同步的常見錯誤或是潛在問題,從官方 Github 說明頁面可以得知分析項目有包含以下內容
並且在規則中有分嚴重程度,且根據分析工具抓到靜態代碼的內容來給於提示與建議,嚴重性分為三類


  • Critical : Code issues that often result in deadlocks
  • Advisory : Code that may perform differently than intended or lead to occasional deadlocks
  • Guideline : Code that deviates from best practices and may limit the benefits of other analyzers



  • 加入範例代碼
    透過上述了解了規則之後,接下來我們加入 Thread blocking  的代碼來簡單示範分析結果,在新增的專案 controller 類別加入常見的 Task.Result 與 Task.Wait 阻塞方法
    1. public class ValuesController : ControllerBase
    2. {
    3. // GET api/values
    4. [HttpGet]
    5. public async void Get()
    6. {
    7. var result = await Task.Run(() => BlockingTask());
    8. }
    9. private static int BlockingTask()
    10. {
    11. // Detected blocking
    12. return MethodAsync().Result;
    13. }
    14.  
    15. private static async Task<int> MethodAsync()
    16. {
    17. await Task.Delay(1000);
    18. return 5;
    19. }
    20.  
    21. //private static object _lock;
    22.  
    23. [HttpGet("/")]
    24. public Task Slower()
    25. {
    26. // Detected blocking in called method
    27. return DoSomethingAsync();
    28. }
    29.  
    30. private async Task DoSomethingAsync()
    31. {
    32. await Task.Delay(1000);
    33.  
    34. // Detected blocking
    35. Task.Run(() => { Thread.Sleep(1000); }).Wait();
    36. }
    37.  
    38. [HttpGet("/hello")]
    39. public string Hello()
    40. {
    41. // Not detected: Thread.Sleep happens at OS level
    42. Thread.Sleep(2000);
    43.  
    44. return "Hello World";
    45. }
    46.  
    47. [HttpGet("/hello-sync-over-async")]
    48. public string HelloSyncOverAsync()
    49. {
    50. // Detected blocking
    51. Task.Delay(2000).Wait();
    52.  
    53. return "Hello World";
    54. }
    55.  
    56. [HttpGet("/hello-async-over-sync")]
    57. public async Task<string> HelloAsyncOverSync()
    58. {
    59. // Detected blocking in called method
    60. var result = await Task.Run(() => BlockingTask());
    61.  
    62. return $"Hello World {result}";
    63. }
    64. [HttpGet("/hello-async")]
    65. public async Task<string> HelloAsync()
    66. {
    67. // No blocking :)
    68. await Task.Delay(2000);
    69.  
    70. return "Hello World";
    71. }
    72.  
    73. [HttpGet("/hello-async-precompleted")]
    74. public async Task<string> HelloAsyncPrecompleted()
    75. {
    76. Task<int> task = MethodAsync();
    77.  
    78. if (!task.IsCompletedSuccessfully)
    79. {
    80. // Await completes the Task without blocking
    81. await task;
    82. }
    83.  
    84. // The task is completed at this point so .Result doesn't trigger blocking
    85. var result = task.Result;
    86.  
    87. return $"Hello World {result}";
    88. }
    89. }
    分析建議
    在安裝完套件之後,可以看到原本看似 peace 的靜態代碼在分析之後有潛在的風險,舉例來說用到 Task.Result ,就會說明目前寫法可能會造成 deadlock,建議改用 await 方式避免
    或是使用 Task.Wait 
    或是方法也會有相關建議
    透過此套件可以提早發現代碼中可能造成的問題,避免上線後才發現影響到用戶,在 Github 網頁有更詳細的介紹與說明,若有興趣了解細節運作可以查看其 Github source code : 傳送門,希望這篇文章有幫助到大家&喜歡 :)

    參考
     vs-threading

    Related Posts:

    • [Benchmark] String 比較字串效能分析前言 在 .NET 開發時很常會用到字串的比對,C# 中提供多種字串比對的方式,這篇文章就列出在 C# 提供的字串比方法,針對這幾種常用的方法使用  BenchmarkDotNet  做效能的測試及比對,並會在 .NET Framework 與 .NET Core 分別測試結果,若有問題或是錯誤的地方歡迎各位給予指導及討論。 測試代碼  測試使用  BenchmarkDotNe… Read More
    • [NET] Task.Run 與 Task.Factory.StartNew前言  從 .NET 4.0 版本新增 TPL (Task Parallel Library) 函式庫,常在公司專案 Code 中可以看到 Task.Run 與 Task.Factory.StartNew 兩種建立任務的方式,某次同事也有提問對兩者的差異性不太明白,因此這篇文章整理自己對於兩者的相關資訊與用法,希望有不清楚或是自己研究錯誤的地方歡迎提出討論 探索問題 Task.Run 與 Task.Factory.StartN… Read More
    • [NETCore] 如何設定 ASP.NET Core 健康檢查(Health Check)功能前言 過去當應用程式開發完成之後,另外一項重要的事情就是建立上線後的監控機制,尤其是重要性高的服務更是不可或缺的事情,有遇過公司是在站台底下放置一個檔案內容文字是OK,在透過工具固定時間去確認網站底下這檔案是否有正常回傳,就可代表網站是否存活者,各種不同的實作方式都可以達到此目的;在 ASP.NET Core 2.2 開始提供 Health Check 中介層 (Middleware),透過 HTTP 方式可以即時取得應用程式的健康狀況… Read More
    • [NETCore] 如何設定 ASP.NET Core 健康檢查(Health Check)功能 - Health Check UI前言 在前一篇針對 ASP.NET Core 2.2 新特性 Health Check功能做基本的介紹,接著要分享的是在 BeatPulse 中實用的功能 Health Check UI,提供 UI 介面顯示及儲存 Health Check 檢查的結果內容,如果有多台時也可以在設定檔加上指定 URL 達到同時監控多台的效果,此篇就針對 Health Check UI 做介紹,若有問題或是錯誤的地方歡迎網路的高手大大給予指導。 Health… Read More
    • [NETCore] 動態 String 字串相加效能比較 前言 在前一篇 [.NETCore] String 字串相加效能比較 對於 C# string 的應用做了一些測試,得到在使用固定字串相加時使用 string 效能反而比 stringBuilder 來的好,在 string  有多種應用情境因此這篇就在針對另一種使用情境針對 string 動態文字相加做比較若有問題或是錯誤的地方歡迎各位給予指導及討論。 測試代碼  測試方式同樣以  B… Read More

    0 意見:

    張貼留言

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

    Design by Anders Noren | Blogger Theme by NewBloggerThemes.com