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

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

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

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

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

1.異步編程(async/await)

核心思想

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

優(yōu)勢(shì)

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

C# 實(shí)現(xiàn)

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

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

關(guān)鍵點(diǎn)

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

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

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

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

核心思想: 

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

優(yōu)勢(shì):

  • 削峰填谷: 突發(fā)的高流量可以被隊(duì)列緩沖,消費(fèi)者按自身能力消費(fèi),避免后端服務(wù)瞬時(shí)過(guò)載崩潰。
  • 解耦: 生產(chǎn)者和消費(fèi)者完全解耦,互不影響,提高系統(tǒng)可靠性和可維護(hù)性。
  • 異步處理: 釋放 Web 服務(wù)器線(xiàn)程,使其專(zhuān)注于處理用戶(hù)請(qǐng)求。
  • 重試機(jī)制: 消息隊(duì)列通常支持消息傳遞失敗后的重試。
// 使用 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ù)(如配置、熱門(mén)商品信息、會(huì)話(huà)狀態(tài))存儲(chǔ)在獨(dú)立于應(yīng)用服務(wù)器、高性能的內(nèi)存緩存服務(wù)(如 Redis, Memcached中。

優(yōu)勢(shì):

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

推薦工具

  • 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ù)庫(kù)優(yōu)化

連接池: 

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

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

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

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

優(yōu)化查詢(xún):

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

NoSQL 考慮: 

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

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

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

  • 常用機(jī)制:lock 語(yǔ)句: 最常用,基于 Monitor 類(lèi),提供互斥鎖。

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

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

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

樂(lè)觀鎖

樂(lè)觀鎖 通過(guò)版本號(hào)(Version)或時(shí)間戳(Timestamp)實(shí)現(xiàn)“無(wú)鎖”并發(fā)控制:

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

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

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

Redis分布式鎖

原理:

基于Redis的原子操作(如SET key value NX PX)實(shí)現(xiàn)互斥訪(fǎng)問(wèn):

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

適用場(chǎng)景

  • 低沖突場(chǎng)景:如讀多寫(xiě)少的業(yè)務(wù)(商品瀏覽、配置讀?。?。

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

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

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

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

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

Monitor 類(lèi): lock 的底層實(shí)現(xiàn),提供更細(xì)粒度控制(如 TryEnterWaitPulse)。

Mutex: 進(jìn)程間或跨 AppDomain 的互斥鎖,重量級(jí)。

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

關(guān)鍵原則:

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

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

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

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

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

對(duì)于需要大量并發(fā)線(xiàn)程的場(chǎng)景,可以使用Task.Run來(lái)啟動(dòng)一個(gè)新任務(wù)到線(xiàn)程池中。

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

這比手動(dòng)創(chuàng)建和銷(xiāo)毀線(xiàn)程更高效。

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

典型誤區(qū)

  1. 過(guò)度使用 Task.Run:I/O 操作直接用 async 而非封裝線(xiàn)程

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

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

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

黃金法則

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

通過(guò)負(fù)載測(cè)試(如 JMeter/LoadRunner)持續(xù)驗(yàn)證系統(tǒng)極限。

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

核心思想

  •  提供線(xiàn)程安全的集合類(lèi),允許多個(gè)線(xiàn)程安全地添加、移除或訪(fǎng)問(wèn)集合中的元素,而無(wú)需開(kāi)發(fā)者手動(dòng)加鎖。

常用類(lèi)

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

優(yōu)勢(shì): 

簡(jiǎn)化多線(xiàn)程編程,避免鎖競(jìng)爭(zhēng)(內(nèi)部使用高效的鎖或無(wú)鎖技術(shù)),提高并發(fā)訪(fǎng)問(wèn)性能。

示例: 

使用 ConcurrentQueue 實(shí)現(xiàn)簡(jiǎn)單的生產(chǎn)者-消費(fèi)者。

using System.Collections.Concurrent;


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

總結(jié)

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

    c# 如何用組合替代繼承

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

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

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

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

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

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

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

最新評(píng)論

纳雍县| 略阳县| 崇义县| 荔浦县| 泰州市| 兰州市| 广昌县| 五河县| 扬州市| 赤峰市| 钦州市| 房产| 湟源县| 南部县| 安泽县| 上林县| 隆化县| 伊春市| 余庆县| 平舆县| 玛沁县| 柳林县| 沈阳市| 南昌县| 湘乡市| 屯门区| 海盐县| 张家界市| 乐清市| 宜良县| 南开区| 九龙坡区| 景谷| 雷波县| 杂多县| 瓮安县| 旺苍县| 浦县| 准格尔旗| 九龙城区| 渑池县|