跟著AI學習C# Day26

📅 Day 26:C# 異步編程進階

? 學習目標:

  • 深入理解 async/await 的底層機制;
  • 掌握 ConfigureAwait(false) 的作用與使用場景;
  • 避免異步死鎖,理解同步上下文(Synchronization Context);
  • 掌握并行任務處理技巧(Parallel, PLINQ);
  • 使用 ValueTask 替代 Task 提升性能;
  • 構建高性能的異步 API;
  • 編寫一個結合多個異步優化技巧的示例程序(如高并發網絡爬蟲)。

🧠 一、回顧 async/await 基礎知識

? asyncawait 是什么?

  • async 標記方法為異步方法;
  • await 用于等待異步操作完成而不阻塞線程。
public async Task<string> DownloadAsStringAsync(string url)
{using var client = new HttpClient();return await client.GetStringAsync(url);
}

? 狀態機原理簡述:

編譯器會將 async 方法轉換為狀態機對象(IAsyncStateMachine),自動管理異步流程和上下文切換。


🔁 二、ConfigureAwait(false) 的意義與使用

? 默認行為(不加 ConfigureAwait(false)

在 UI 應用中(如 WPF、WinForms),默認會捕獲當前的 SynchronizationContext,以便 await 后繼續回到 UI 線程執行后續代碼。

??問題:可能導致死鎖!

如果你在 UI 線程調用了 .Result.Wait(),而異步方法又試圖回到 UI 線程,就會發生死鎖。

? 正確做法:庫方法應使用 ConfigureAwait(false)

public async Task<string> GetDataAsync()
{string result = await SomeNetworkCallAsync().ConfigureAwait(false);return Process(result);
}

?? 在類庫中始終使用 ConfigureAwait(false),除非你明確需要返回到特定上下文(如 UI)。


💀 三、避免異步死鎖

? 錯誤寫法(UI 線程中):

var result = GetDataAsync().Result;

這會導致主線程被阻塞,并且 await 后想回到這個線程,但該線程正等著結果,導致死鎖。

? 正確寫法:

var result = await GetDataAsync();

或者,在非 UI 場景中使用:

Task.Run(async () => await GetDataAsync()).Wait();

🧩 四、并行任務處理(Parallel & PLINQ)

? Parallel.For / Parallel.ForEach

適用于 CPU 密集型任務的并行執行。

Parallel.For(0, 10, i =>
{Console.WriteLine($"處理 {i},線程ID:{Thread.CurrentThread.ManagedThreadId}");
});

? PLINQ(Parallel LINQ)

并行查詢,適合大數據集合處理:

var numbers = Enumerable.Range(1, 1000000);var result = numbers.AsParallel().Where(n => n % 3 == 0).Sum();Console.WriteLine("總和:" + result);

🧱 五、ValueTask vs Task(.NET Core 2.1+)

? Task<T> 的缺點:

每次調用都會分配內存(堆上創建對象),對高頻調用或熱路徑有性能影響。

? ValueTask<T> 的優勢:

  • 如果結果已知(緩存命中、立即完成),則不分配;
  • 適用于“大多數快速完成”的異步操作。
public ValueTask<int> GetCachedValueAsync()
{if (_cache.HasValue)return new ValueTask<int>(_cache.Value);elsereturn new ValueTask<int>(GetValueFromNetworkAsync());
}

? 注意:不能多次 await,否則可能拋出異常。


🔄 六、自定義異步狀態機(高級)

你可以通過實現 IValueTaskSource<TResult> 來構建自己的 ValueTask 實現,但這通常只在高性能框架開發中使用。

示例略(復雜度較高,需深入理解狀態機機制)。


🧪 七、實戰練習:高并發網頁爬蟲

功能要求:

  • 并發下載多個網頁;
  • 使用 HttpClient 異步請求;
  • 避免死鎖;
  • 使用 ValueTask 緩存熱門頁面;
  • 支持配置最大并發數;
  • 輸出各頁面大小。
示例代碼框架:
class WebCrawler
{private readonly HttpClient _client = new();private readonly ConcurrentDictionary<string, string> _cache = new();public async Task<int> CrawlPageAsync(string url){// 使用緩存if (_cache.TryGetValue(url, out var cached))return cached.Length;// 下載網頁string content = await _client.GetStringAsync(url).ConfigureAwait(false);_cache.TryAdd(url, content);return content.Length;}public async Task RunAsync(IEnumerable<string> urls){var tasks = urls.Select(url =>Task.Run(async () =>{int length = await CrawlPageAsync(url).ConfigureAwait(false);Console.WriteLine($"{url} 長度:{length}");}));await Task.WhenAll(tasks);}
}

📝 小結

今天你學會了:

  • ConfigureAwait(false) 的作用與使用時機;
  • 如何避免異步死鎖;
  • 使用 ParallelPLINQ 實現并行任務;
  • ValueTask 的優勢及其適用場景;
  • 自定義異步狀態機的基本概念;
  • 編寫了一個高并發網頁爬蟲的異步優化示例。

掌握這些高級異步編程技巧,能顯著提升應用程序的響應性、吞吐量和資源利用率,尤其在 Web API、微服務、桌面應用等場景中尤為重要。


🧩 下一步學習方向(Day 27)

明天我們將進入一個新的主題 —— C# 中的反射(Reflection)與元編程,你將學會:

  • 如何在運行時動態加載類型、調用方法;
  • 獲取類成員信息(屬性、方法、構造函數);
  • 使用 System.Reflection.Emit 創建動態程序集;
  • 反射在依賴注入、序列化、ORM 等框架中的應用;
  • 性能優化技巧(緩存反射結果、使用表達式樹代替 Invoke);
  • 編寫一個基于反射的通用對象克隆器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85976.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85976.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85976.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Scrapy | 通過爬取豆瓣Top250電影信息來學習在中間件中應用隨機請求頭和代理ip

中間件的使用 1.scrapyl中間件的分類和作用1.1 scrapy中間件的分類1.2 scrapy中間的作用:預處理request和response對象2.下載中間件的使用方法:3.定義實現隨機User-Agent的下載中間件3.1 實戰:爬取豆瓣Top250電影信息3.2 中間件使用實現隨機User-Agent4. 代理ip的使用4.1思路…

【深度學習】深度學習入門:從理論到實踐的全面指南

深度學習入門&#xff1a;從理論到實踐的全面指南 深度學習&#xff1a;開啟人工智能新時代的鑰匙一、深度學習的廣泛應用場景1.1 改變生活的深度學習應用1.2 行業變革案例深度解析案例一&#xff1a;深度學習檢測皮膚癌案例二&#xff1a;移動端OCR技術突破案例三&#xff1a;…

MySQL 數據庫操作完整指南

MySQL 數據庫操作完整指南 目錄 創建數據庫 連接數據庫 創建表 約束詳解 插入數據 查詢數據 多表聯合查詢 連接查詢 高級查詢 更新數據 刪除數據 視圖詳解 存儲過程詳解 函數詳解 觸發器 事務處理 索引優化 安全性管理 備份和恢復 性能優化 刪除表和數據庫 1. 創建數據庫 基…

Java面試復習:面向對象編程、Java 8新特性與Spring

Java面試復習&#xff1a;面向對象編程、Java 8新特性與Spring 面向對象編程 概念解析&#xff1a;面向對象編程&#xff08;OOP&#xff09;是將現實世界中的概念抽象為軟件模型的編程范式&#xff0c;包括封裝、繼承和多態。 核心原理&#xff1a; 封裝&#xff1a;通過訪…

藍牙數據通訊,實現內網電腦訪問外網電腦

最近突然想到了一個可以繞開單位安全管控軟件&#xff0c;讓單位內部辦公電腦連上外網的方法。大概是這個樣子&#xff0c;讓單位辦公電腦與自己的外網電腦進行藍牙配對&#xff0c;然后用配對成功的藍牙進行網絡數據交互。這里大家可能會想用一下藍牙的網絡共享功能&#xff0…

硬件面經-具身機器人通用技術要求

目錄 簡介 場景 技術面試 設計知識點 總結 簡介 最近機器人特別的火。所以收集了一些關于機器人的面試及要求 場景 目前具身機器人賽道可謂是十分火熱,全國大大小小崛起了幾十家具身機器人公司,國外比較出名的有波士頓動力,特斯拉等,國內目前比較火的就是宇樹,眾擎…

DeepSeek生成HTML5圖片拼接工具

讓DeepSeek生成一個HTML5圖片拼接工具&#xff0c;給的提示詞如下 提示詞(prompt) 幫我生成一個可以將兩張圖片拼接到一起的程序 支持橫向拼接和豎向拼接&#xff0c;可以用html5實現功能嗎&#xff1f; DeepSeek大概20秒左右就做好了&#xff0c;而且像這么簡單的功能的話也沒…

Java面試復習指南:Java基礎、面向對象編程與并發編程

Java面試復習指南&#xff1a;Java基礎、面向對象編程與并發編程 1. Java基礎 概念解析: Java是一種面向對象的編程語言&#xff0c;具有跨平臺的特性。 核心原理: JVM負責Java程序的跨平臺運行&#xff0c;通過字節碼來實現。 高頻面試問題: Java如何實現跨平臺&#xff…

LeeCode2566替換一個數字后的最大差值

項目場景&#xff1a; 給你一個整數 num 。你知道 Danny Mittal 會偷偷將 0 到 9 中的一個數字 替換 成另一個數字。 請你返回將 num 中 恰好一個 數字進行替換后&#xff0c;得到的最大值和最小值的差為多少。 注意&#xff1a; 當 Danny 將一個數字 d1 替換成另一個數字 …

李宏毅2025《機器學習》第三講-AI的腦科學

在之前的課程中探討了如何利用大模型構建AI Agent,本科將暫時放下應用層面的探索,拿起“手術刀”和“顯微鏡”,深入剖析LLM的“大腦”,帶您踏上一場“AI腦神經科學”的旅程。課程不討論模型的訓練過程,而是假設我們擁有一個已經訓練好的、功能完備的LLM。我們的目標是:理…

CVPR 2025 | 微米級光影CT精度!復旦騰訊優圖開源Real-IAD D3數據集

【導讀】 本文介紹了復旦聯合騰訊優圖發布高精度多模態數據集Real-IAD D&#xff0c;并基于此數據集提出了一種創新的多模態融合檢測方法&#xff0c;數據集已被CVPR 2025收錄&#xff0c;并開源。>>更多資訊可加入CV技術群獲取了解哦~ 目錄 一、Real-IAD D的創新之處…

解決mysql左連接加where就不會保留左表中的全部數據的問題

在SQL中使用MySQL的LEFT JOIN操作時,如果加入了WHERE條件,確實會影響結果集的完整性,特別是如果你在WHERE條件中使用了JOIN的另一張表中的字段作為過濾條件。這是因為當你在WHERE子句中加入了對JOIN另一張表的過濾條件時,實際上你是在執行一個INNER JOIN(內連接)而非LEFT…

算法與數據結構:動態規劃DP

文章目錄 動態規劃算法全面解析一、核心思想與基本概念二、動態規劃與其他算法的區別三、動態規劃的解題步驟四、經典案例解析1. **斐波那契數列&#xff08;Fibonacci&#xff09;**2. **0-1背包問題&#xff08;0-1 Knapsack&#xff09;**3. **最長公共子序列&#xff08;LC…

Coilcraft電感上的橫線是什么意思?電感有方向么?

通常我們會認為電容、電感、電阻這幾類無源器件沒有方向性&#xff0c;在布局和貼片時可以任意方向放置&#xff0c;也不會在PCB上增加絲印標識說明其方向。與此相互印證的是&#xff0c;電容表面無絲印&#xff0c;無法識別方向&#xff1b;電阻表面一般只有包含阻值大小的數字…

通過Docker掛載nginx并修改頁面

1&#xff1a;通過docker創建nginx&#xff1a; 首先關閉原來的Docker&#xff08;防止端口號沖突&#xff09; sudo nginx -s stop 直接啟動 Nginx 進程 sudo nginx 啟動nginx&#xff1a; docker run -di --namemynginx -p 80:80 nginx cd /etc/nginx docker run -d …

力扣1124. 表現良好的最長時間段

這一題我看到數據范圍是10^4&#xff0c;暗自竊喜能用雙重循環&#xff0c;看題目是典型的前綴和哈希。不過需要一個轉換將大于8小時的轉化為1&#xff0c;其他都為-1&#xff0c;方便計算&#xff0c;之前的題目中也有這種方法。 那這樣就簡單了 class Solution { public:int…

EDA2算法速通(編者崩潰版)

這個內容是用來回憶一下EDA2涉及的算法和解題的主要步驟&#xff1a; 有疑問或發現錯誤可以私信來討論 高級綜合概述 柏拉圖優化&#xff1a;這個是來判斷是否有哪些節點能完全被其他節點優化掉。比如&#xff08;1,2&#xff09;這個節點就可以完全優化&#xff08;3,4&…

雷池waf配置第三方登錄-釘釘配置詳細教程

雷池waf配置第三方登錄-釘釘配置詳細教程 前往釘釘開放平臺https://open.dingtalk.com/ 選擇一個登錄方式登錄釘釘開放平臺 選擇一個自己所管理的組織 登錄成功后點擊我的后臺 選擇應用開發 在釘釘應用下點擊創建應用 填寫應用名稱和應用描述后點擊保存 點擊網頁…

神經網絡中的均方誤差(Mean Squared Error)詳解

引言 在機器學習和神經網絡領域&#xff0c;損失函數&#xff08;Loss Function&#xff09;是衡量模型預測值與真實值之間差異的關鍵指標。均方誤差&#xff08;Mean Squared Error, MSE&#xff09;作為一種經典的損失函數&#xff0c;因其簡單性、可解釋性和數學上的優良性…

day036-lsyncd實時同步服務與網站存儲架構

文章目錄 1. 實時同步工具2. lsyncd 實時同步服務2.1 環境準備2.2 rsync準備2.2.1 服務端檢查2.2.2 客戶端檢查2.2.3 備份測試 2.3 配置lsyncd2.3.1 安裝軟件2.3.2 編寫配置文件 2.4 測試 3. 案例-網站存儲架構3.1 rsync服務配置3.1.1 服務端配置3.1.2 客戶端配置 3.2 lsyncd服…