最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#之高并發(fā)處理過程

 更新時間:2026年05月25日 16:46:35   作者:陳同學(xué)呀  
本文深入探討了C#中處理高并發(fā)問題的策略,包括異步編程、分布式架構(gòu)與數(shù)據(jù)庫優(yōu)化,異步編程通過`async/await`避免線程阻塞,提升系統(tǒng)性能;分布式架構(gòu)如消息隊列和緩存則實現(xiàn)解耦與削峰填谷;數(shù)據(jù)庫優(yōu)化則強調(diào)連接池與異步操作,確保高效處理大量并發(fā)請求

高并發(fā)本質(zhì)是系統(tǒng)在單位時間內(nèi)處理大量并行請求的能力。

在C#中處理這個問題需要分層解決:首先是架構(gòu)層面,比如是否采用分布式;然后是語言特性層面,比如異步編程;最后是基礎(chǔ)設(shè)施層面,比如數(shù)據(jù)庫優(yōu)化。

1.異步編程(async/await)

核心思想

避免阻塞線程。當(dāng)一個操作(如 I/O - 文件讀寫、網(wǎng)絡(luò)請求、數(shù)據(jù)庫查詢)需要等待外部資源時,釋放當(dāng)前線程去處理其他請求,待操作完成后再由線程池分配線程繼續(xù)執(zhí)行。

優(yōu)勢

顯著提高線程池線程的利用率(一個線程可處理多個請求),用更少的線程服務(wù)更多的并發(fā)請求,減少線程上下文切換開銷,提高系統(tǒng)吞吐量和響應(yīng)能力。

C# 實現(xiàn)

 使用 async 關(guān)鍵字標(biāo)記異步方法,在需要等待的操作前使用 await 關(guān)鍵字。

public async Task<ActionResult> GetData()
{
    var data = await _dbContext.Data.ToListAsync(); // 異步數(shù)據(jù)庫操作
    return Ok(data);
}

關(guān)鍵點

  • 所有 I/O 操作(數(shù)據(jù)庫、網(wǎng)絡(luò)、文件)必須異步

  • 避免 Task.Wait() 或 Task.Result(會導(dǎo)致死鎖)

2. 分布式架構(gòu)

(1) 消息隊列(削峰填谷)

核心思想: 

  • 將耗時的、非實時的操作(如發(fā)送郵件、生成報告、復(fù)雜數(shù)據(jù)處理)異步化。
  • 請求到達后,將任務(wù)信息放入消息隊列(如 RabbitMQ, Azure Service Bus, Kafka, Amazon SQS),立即返回響應(yīng)。
  • 后臺有專門的“消費者”進程從隊列中取出消息并處理。

優(yōu)勢:

  • 削峰填谷: 突發(fā)的高流量可以被隊列緩沖,消費者按自身能力消費,避免后端服務(wù)瞬時過載崩潰。
  • 解耦: 生產(chǎn)者和消費者完全解耦,互不影響,提高系統(tǒng)可靠性和可維護性。
  • 異步處理: 釋放 Web 服務(wù)器線程,使其專注于處理用戶請求。
  • 重試機制: 消息隊列通常支持消息傳遞失敗后的重試。
// 使用 RabbitMQ.Client 發(fā)送
using var channel = _connection.CreateModel();
channel.QueueDeclare("orders");
var body = Encoding.UTF8.GetBytes(orderJson);
channel.BasicPublish("", "orders", body); // 異步解耦
  • 推薦工具RabbitMQ、Kafka、Azure Service Bus

(2)分布式緩存

核心思想: 

  • 將頻繁讀取但不經(jīng)常變化的數(shù)據(jù)(如配置、熱門商品信息、會話狀態(tài))存儲在獨立于應(yīng)用服務(wù)器、高性能的內(nèi)存緩存服務(wù)(如 Redis, Memcached中。

優(yōu)勢:

  • 極大減少對后端數(shù)據(jù)庫(通常是性能瓶頸)的訪問次數(shù)。
  • 數(shù)據(jù)存儲在內(nèi)存中,訪問速度極快。
  • 支持分布式部署,多個應(yīng)用實例共享同一緩存,保證數(shù)據(jù)一致性。
  • 提高應(yīng)用的可擴展性(水平擴展應(yīng)用服務(wù)器時,緩存層通常更容易擴展)

推薦工具

  • Redis, Memcached
// 使用 StackExchange.Redis
IDatabase cache = Connection.GetDatabase();
await cache.StringSetAsync("key", "value", TimeSpan.FromMinutes(10));
string value = await cache.StringGetAsync("key");

3. 數(shù)據(jù)庫優(yōu)化

連接池: 

  • ADO.NET 和 ORM(如 EF Core)默認(rèn)管理數(shù)據(jù)庫連接池。

  • 確保配置合理的 MinPoolSize 和 MaxPoolSize。

異步數(shù)據(jù)庫操作 

  • 務(wù)必使用 ORM 或 ADO.NET 提供的異步方法(如 ToListAsync()SaveChangesAsync()ExecuteReaderAsync())來執(zhí)行數(shù)據(jù)庫查詢和命令。

優(yōu)化查詢:

  • 使用索引避免全表掃描。
  • 只查詢需要的字段(Select)。
  • 避免 N+1 查詢問題(EF Core 中注意使用 Include 或投影)。
  • 合理設(shè)計數(shù)據(jù)模型。
  • 考慮讀寫分離、分庫分表(在數(shù)據(jù)量極大時)。

NoSQL 考慮: 

  • 對于某些特定場景(如文檔存儲、鍵值對、寬列存儲、圖數(shù)據(jù)庫),NoSQL 數(shù)據(jù)庫(如 MongoDB, Cassandra, Cosmos DB)可能比關(guān)系型數(shù)據(jù)庫(如 SQL Server, PostgreSQL)更適合高并發(fā)讀寫和水平擴展。

4. 使用鎖(lock)和互斥量(Mutex)

  • 核心思想: 當(dāng)多個線程需要訪問共享資源(如靜態(tài)變量、單例實例、文件句柄)時,必須協(xié)調(diào)它們的訪問,防止數(shù)據(jù)損壞或狀態(tài)不一致。

  • 常用機制:lock 語句: 最常用,基于 Monitor 類,提供互斥鎖。

雖然鎖在高并發(fā)場景下可能會引起性能瓶頸,但在某些情況下仍然需要使用。確保只在必要時使用,并盡可能減少鎖定范圍。

private object lockObject = new object();
public void ProcessData(int data)
{
    lock (lockObject)
    {
        // 執(zhí)行需要同步的代碼塊
    }
}

樂觀鎖和Redis分布式鎖都是處理高并發(fā)場景的核心方案

樂觀鎖

樂觀鎖 通過版本號(Version)或時間戳(Timestamp)實現(xiàn)“無鎖”并發(fā)控制:

  • 讀階段:讀取數(shù)據(jù)時記錄當(dāng)前版本號。
  • 寫階段:提交更新前校驗版本號是否未變化,若變化則重試或失敗。

典型實現(xiàn)包括:

  • 數(shù)據(jù)庫樂觀鎖:通過SQL語句(如UPDATE ... WHERE version=old_version)。
  • Redis的WATCH/MULTI:監(jiān)視Key變化,事務(wù)中執(zhí)行CAS操作

Redis分布式鎖

原理:

基于Redis的原子操作(如SET key value NX PX)實現(xiàn)互斥訪問:

  • 加鎖:通過SETNX設(shè)置唯一值并附加超時時間。
  • 續(xù)期:Redisson的Watchdog線程自動延長鎖有效期。
  • 釋放:校驗持有者身份后刪除Key。

適用場景

  • 低沖突場景:如讀多寫少的業(yè)務(wù)(商品瀏覽、配置讀?。?/p>

  • 突發(fā)流量:秒殺系統(tǒng)中庫存扣減(配合重試機制)。

  • 需高吞吐:避免鎖競爭,提升并發(fā)能力

樂觀鎖和Redis分布式鎖是處理高并發(fā)的互補方案而非互斥:

  • 樂觀鎖:輕量、高吞吐,適合低沖突場景,需防范ABA問題。
  • Redis分布式鎖:強一致、易用,需優(yōu)化主從容錯與鎖粒度。

實際系統(tǒng)中常組合使用(如Redis鎖攔截請求+數(shù)據(jù)庫樂觀鎖保證最終一致)

Monitor 類: lock 的底層實現(xiàn),提供更細粒度控制(如 TryEnterWaitPulse)。

Mutex: 進程間或跨 AppDomain 的互斥鎖,重量級。

 //當(dāng)前電腦只能啟動一個WCS程序
 using (System.Threading.Mutex m = new System.Threading.Mutex(true, AppConfig.Instance.GetConfig("主界面名稱"), out Started))
 {
     if (Started)
     {
         if (DbManagerBase.Instance.GetDbTime() == false)
         {
             MessageBox.Show("數(shù)據(jù)庫連接失敗,請檢查原因!");
         }
         else
         {
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
             Application.Run(new FrmMain());
         }
     }
     else
     {
         LibManager.WriteLog("WCS程序啟動失敗,與運行中WCS程序的主界面名稱重復(fù)", RecordLogTypeEnum.Error.ToString(), "");
         MessageBox.Show("當(dāng)前WCS程序已啟動!");
     }
 }

關(guān)鍵原則:

  • 最小化鎖范圍: 只在絕對必要的地方加鎖,并盡快釋放鎖。

  • 避免鎖嵌套: 容易導(dǎo)致死鎖。

  • 鎖粒度: 根據(jù)共享資源的范圍選擇合適的鎖(細粒度鎖通常并發(fā)性更好)。

  • 優(yōu)先使用并發(fā)集合: 在可能的情況下,用 ConcurrentDictionary 等代替自己用鎖實現(xiàn)的集合

5. 使用線程池(ThreadPool)和Task.Run

對于需要大量并發(fā)線程的場景,可以使用Task.Run來啟動一個新任務(wù)到線程池中。

.NET 運行時維護一個預(yù)先創(chuàng)建的線程池,用于執(zhí)行后臺任務(wù)和處理異步回調(diào)。

這比手動創(chuàng)建和銷毀線程更高效。

Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
    tasks[i] = Task.Run(() => DoWork());
}
await Task.WhenAll(tasks);

典型誤區(qū)

  1. 過度使用 Task.Run:I/O 操作直接用 async 而非封裝線程

  2. 全局靜態(tài)鎖:導(dǎo)致無謂的線程阻塞

  3. 同步調(diào)用異步方法GetAwaiter().GetResult() 引發(fā)死鎖

  4. 忽略連接池配置:數(shù)據(jù)庫連接成為瓶頸

黃金法則

異步化所有 I/O 路徑 + 避免共享狀態(tài) + 隊列解耦

通過負(fù)載測試(如 JMeter/LoadRunner)持續(xù)驗證系統(tǒng)極限。

6. 并發(fā)集合 (System.Collections.Concurrent)

核心思想

  •  提供線程安全的集合類,允許多個線程安全地添加、移除或訪問集合中的元素,而無需開發(fā)者手動加鎖。

常用類

  • ConcurrentQueue<T>: 先進先出 (FIFO) 隊列。
  • ConcurrentStack<T>: 后進先出 (LIFO) 棧。
  • ConcurrentDictionary<TKey, TValue>: 鍵值對字典。
  • ConcurrentBag<T>: 無序集合,適用于對象池等場景。
  • BlockingCollection<T>: 提供阻塞和限制功能的集合,常用于生產(chǎn)者-消費者模式。

優(yōu)勢: 

簡化多線程編程,避免鎖競爭(內(nèi)部使用高效的鎖或無鎖技術(shù)),提高并發(fā)訪問性能。

示例: 

使用 ConcurrentQueue 實現(xiàn)簡單的生產(chǎn)者-消費者。

using System.Collections.Concurrent;


private static readonly ConcurrentDictionary<Type, string> assemblyQualifiedNameCache = new ConcurrentDictionary<Type, string>();

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#語言中條件與&&與條件或||的區(qū)別

    C#語言中條件與&&與條件或||的區(qū)別

    這篇文章主要介紹了&&:邏輯與,前后條件同時滿足表達式為真 ||:邏輯或,前后條件只要有一個滿足表達式為真,下面結(jié)合案例給大家介紹,需要的朋友可以參考下
    2015-07-07
  • C#/VB.NET實現(xiàn)在PDF文檔中插入,替換或刪除圖片

    C#/VB.NET實現(xiàn)在PDF文檔中插入,替換或刪除圖片

    這篇文章主要為大家詳細介紹了如何使用 Spire.PDF for .NET 通過程序在 PDF 文檔中插入、替換或刪除圖片,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • C#類中屬性與成員變量的使用小結(jié)

    C#類中屬性與成員變量的使用小結(jié)

    本篇文章主要是對C#類中屬性與成員變量的使用進行了總結(jié)介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • C#實現(xiàn)程序單例日志輸出功能

    C#實現(xiàn)程序單例日志輸出功能

    這篇文章主要為大家詳細介紹了C#實現(xiàn)程序單例日志輸出功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • C# WPF實現(xiàn)讀寫CAN數(shù)據(jù)

    C# WPF實現(xiàn)讀寫CAN數(shù)據(jù)

    這篇文章主要介紹了C# WPF實現(xiàn)讀寫CAN數(shù)據(jù),文中通過代碼示例給大家講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • C#實現(xiàn)復(fù)雜XML的序列化與反序列化

    C#實現(xiàn)復(fù)雜XML的序列化與反序列化

    這篇文章主要介紹了C#實現(xiàn)復(fù)雜XML的序列化與反序列化的方法,是非常實用的一個技巧,需要的朋友可以參考下
    2014-09-09
  • c# 如何用組合替代繼承

    c# 如何用組合替代繼承

    這篇文章主要介紹了c# 如何用組合替代繼承,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-02-02
  • C#獲取本地IP的四種方式示例詳解

    C#獲取本地IP的四種方式示例詳解

    這篇文章主要介紹了C#獲取本地IP的四種方式示例詳解, 文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • C#對XtraGrid控件實現(xiàn)主從表關(guān)系綁定

    C#對XtraGrid控件實現(xiàn)主從表關(guān)系綁定

    這篇文章介紹了C#對XtraGrid控件實現(xiàn)主從表關(guān)系綁定的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例分享

    c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例分享

    這篇文章主要介紹了使用c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例,需要的朋友可以參考下
    2014-02-02

最新評論

齐河县| 屯昌县| 阜阳市| 牟定县| 郸城县| 娄烦县| 延津县| 新安县| 凤城市| 安顺市| 体育| 克拉玛依市| 湘潭县| 明水县| 钦州市| 盐池县| 巴东县| 曲麻莱县| 桦南县| 伊川县| 福泉市| 承德市| 柳林县| 青冈县| 大港区| 三都| 若尔盖县| 榕江县| 马山县| 漠河县| 永康市| 武山县| 阿城市| 青铜峡市| 剑河县| 延长县| 剑川县| 仪征市| 文化| 汾阳市| 应城市|