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

C#使用SemaphoreSlim進行并發(fā)控制的最佳實踐

 更新時間:2026年04月15日 09:13:15   作者:oliver.chau  
本文介紹了在C#中控制異步并發(fā)的標(biāo)準(zhǔn)解決方案SemaphoreSlim,,首先分析了不加控制的并發(fā)可能導(dǎo)致的問題和錯誤解決方案,接著詳細(xì)介紹了SemaphoreSlim的工作原理及其在生產(chǎn)環(huán)境中的使用方法,需要的朋友可以參考下

在現(xiàn)代異步編程中,高效處理I/O密集型操作是提升應(yīng)用性能的關(guān)鍵。然而,不加控制的并發(fā)往往會導(dǎo)致災(zāi)難性后果——下游服務(wù)過載、數(shù)據(jù)庫連接池耗盡、內(nèi)存暴漲。本文將深入探討C#中控制異步并發(fā)的標(biāo)準(zhǔn)解決方案:SemaphoreSlim,并提供生產(chǎn)級別的使用模式。

一、為什么需要控制異步并發(fā)?

假設(shè)我們需要處理1000個訂單,每個訂單需要調(diào)用一個外部支付接口:

// 危險的反模式:瞬間發(fā)起1000個HTTP請求
public async Task ProcessOrdersDangerously(List<Order> orders)
{
    var tasks = orders.Select(order => CallPaymentApiAsync(order));
    await Task.WhenAll(tasks); // 瞬間并發(fā)過高!
}

這種方式會同時發(fā)起1000個HTTP請求,可能導(dǎo)致:

  • 目標(biāo)API服務(wù)器拒絕服務(wù)
  • 本地網(wǎng)絡(luò)連接池耗盡
  • 內(nèi)存使用量激增
  • 整體性能反而下降

二、錯誤解決方案辨析

在探索解決方案時,開發(fā)者常走入以下誤區(qū):

1. 誤用Parallel.ForEach

// 錯誤:Parallel.ForEach用于CPU密集型同步操作
Parallel.ForEach(orders, async order => 
{
    await CallPaymentApiAsync(order); // 實際上同步執(zhí)行
});

Parallel.ForEach 設(shè)計用于同步CPU密集型操作,將其用于異步I/O操作不僅無法有效控制并發(fā),還會造成線程池的浪費。

2. 分批處理的問題

// 次優(yōu)方案:雖能限制并發(fā),但效率低下
for (int i = 0; i < orders.Count; i += 10)
{
    var batch = orders.Skip(i).Take(10);
    await Task.WhenAll(batch.Select(CallPaymentApiAsync));
    await Task.Delay(100); // 人工延遲降低效率
}

這種方法雖然限制了并發(fā)數(shù),但批次間的等待會導(dǎo)致總體處理時間延長,無法充分利用資源。

三、SemaphoreSlim:異步并發(fā)的標(biāo)準(zhǔn)解決方案

SemaphoreSlim 是.NET Framework 4.5引入的輕量級信號量,專為async/await設(shè)計,是控制異步并發(fā)的事實標(biāo)準(zhǔn)。

核心工作機制

public class AsyncConcurrencyController
{
    // 初始化信號量,設(shè)置最大并發(fā)數(shù)為5
    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(5, 5);
    
    public async Task ProcessWithConcurrencyControl(List<Item> items)
    {
        var tasks = items.Select(async item =>
        {
            // 關(guān)鍵:異步等待信號量,不阻塞線程
            await _semaphore.WaitAsync();
            try
            {
                // 執(zhí)行受保護的異步操作
                await ProcessItemAsync(item);
            }
            finally
            {
                // 關(guān)鍵:必須釋放信號量
                _semaphore.Release();
            }
        });
        
        await Task.WhenAll(tasks);
    }
}

工作原理可視化

初始狀態(tài): [√][√][√][√][√] [ ][ ][ ][ ][ ] ... (20個任務(wù))
          ↑ 5個并發(fā)槽可用

執(zhí)行過程:
1. 任務(wù)1-5立即獲取信號量并執(zhí)行
2. 任務(wù)6-20在WaitAsync()處等待
3. 任務(wù)1完成后釋放信號量
4. 任務(wù)6立即獲取釋放的信號量并開始執(zhí)行
5. 如此循環(huán),始終保持最多5個并發(fā)

四、生產(chǎn)環(huán)境最佳實踐

1. 基礎(chǔ)封裝模式

public class ConcurrentExecutor
{
    private readonly SemaphoreSlim _semaphore;
    
    public ConcurrentExecutor(int maxConcurrency)
    {
        _semaphore = new SemaphoreSlim(maxConcurrency, maxConcurrency);
    }
    
    public async Task<TResult> ExecuteAsync<TResult>(
        Func<Task<TResult>> operation, 
        CancellationToken cancellationToken = default)
    {
        await _semaphore.WaitAsync(cancellationToken);
        try
        {
            return await operation();
        }
        finally
        {
            _semaphore.Release();
        }
    }
}

2. 帶超時控制的增強版本

public async Task<T> ExecuteWithTimeoutAsync<T>(
    Func<Task<T>> operation,
    TimeSpan timeout,
    CancellationToken cancellationToken = default)
{
    // 嘗試在指定時間內(nèi)獲取信號量
    bool acquired = await _semaphore.WaitAsync(timeout, cancellationToken);
    
    if (!acquired)
        throw new TimeoutException($"無法在{timeout.TotalSeconds}秒內(nèi)獲取執(zhí)行許可");
    
    try
    {
        return await operation();
    }
    finally
    {
        _semaphore.Release();
    }
}

3. 批量處理與進度報告

public async Task ProcessBatchWithProgressAsync<T>(
    IEnumerable<T> items,
    Func<T, Task> processor,
    int maxConcurrency,
    IProgress<int> progress = null,
    CancellationToken cancellationToken = default)
{
    var semaphore = new SemaphoreSlim(maxConcurrency, maxConcurrency);
    int total = items.Count();
    int completed = 0;
    
    var tasks = items.Select(async item =>
    {
        await semaphore.WaitAsync(cancellationToken);
        try
        {
            await processor(item);
        }
        finally
        {
            semaphore.Release();
            Interlocked.Increment(ref completed);
            progress?.Report((completed * 100) / total);
        }
    });
    
    await Task.WhenAll(tasks);
}

五、高級應(yīng)用場景

1. 分層并發(fā)控制

// 場景:每個用戶最多5個并發(fā),全局最多50個并發(fā)
public class TieredConcurrencyController
{
    private readonly SemaphoreSlim _globalSemaphore = new(50, 50);
    private readonly ConcurrentDictionary<string, SemaphoreSlim> _userSemaphores = new();
    
    public async Task ExecuteForUserAsync(string userId, Func<Task> operation)
    {
        // 獲取用戶級信號量(每個用戶獨立)
        var userSemaphore = _userSemaphores.GetOrAdd(userId, _ => new SemaphoreSlim(5, 5));
        
        // 先獲取全局許可
        await _globalSemaphore.WaitAsync();
        await userSemaphore.WaitAsync();
        
        try
        {
            await operation();
        }
        finally
        {
            userSemaphore.Release();
            _globalSemaphore.Release();
        }
    }
}

2. 與Polly結(jié)合實現(xiàn)彈性并發(fā)

public class ResilientConcurrentExecutor
{
    private readonly SemaphoreSlim _semaphore;
    private readonly AsyncPolicy _retryPolicy;
    
    public async Task<T> ExecuteWithRetryAsync<T>(
        Func<Task<T>> operation, 
        int maxConcurrency)
    {
        _semaphore = new SemaphoreSlim(maxConcurrency, maxConcurrency);
        _retryPolicy = Policy
            .Handle<HttpRequestException>()
            .WaitAndRetryAsync(3, retryAttempt => 
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
        
        await _semaphore.WaitAsync();
        try
        {
            return await _retryPolicy.ExecuteAsync(operation);
        }
        finally
        {
            _semaphore.Release();
        }
    }
}

六、性能調(diào)優(yōu)與監(jiān)控

1. 動態(tài)調(diào)整并發(fā)數(shù)

public class AdaptiveConcurrencyController
{
    private SemaphoreSlim _semaphore;
    private readonly int _initialConcurrency;
    private readonly object _lock = new object();
    
    public void AdjustConcurrencyBasedOnMetrics(
        double successRate, 
        double avgLatency, 
        int errorCount)
    {
        lock (_lock)
        {
            int newLimit = CalculateOptimalConcurrency(
                successRate, avgLatency, errorCount);
            
            if (newLimit != _semaphore.CurrentCount)
            {
                var oldSemaphore = _semaphore;
                _semaphore = new SemaphoreSlim(newLimit, newLimit);
                
                // 遷移正在等待的任務(wù)到新信號量
                MigrateWaiters(oldSemaphore, _semaphore);
            }
        }
    }
}

2. 監(jiān)控信號量狀態(tài)

public class MonitoredSemaphoreSlim : SemaphoreSlim
{
    public int CurrentWaitCount { get; private set; }
    public TimeSpan AverageWaitTime { get; private set; }
    
    public new async Task WaitAsync(CancellationToken cancellationToken)
    {
        var stopwatch = Stopwatch.StartNew();
        CurrentWaitCount++;
        
        try
        {
            await base.WaitAsync(cancellationToken);
        }
        finally
        {
            stopwatch.Stop();
            CurrentWaitCount--;
            UpdateAverageWaitTime(stopwatch.Elapsed);
        }
    }
}

七、注意事項與常見陷阱

  1. 避免信號量泄漏:務(wù)必在finally塊中調(diào)用Release(),確保異常情況下也能釋放
  2. 不要過度限制:根據(jù)目標(biāo)服務(wù)的實際能力設(shè)置合理的并發(fā)數(shù)
  3. 區(qū)分資源類型
    • CPU密集型:使用Parallel.ForEach或TPL Dataflow
    • I/O密集型:使用SemaphoreSlim + async/await
  4. 考慮取消支持:始終傳遞CancellationTokenWaitAsync()

八、總結(jié)

SemaphoreSlim 是C#異步編程中控制并發(fā)度的標(biāo)準(zhǔn)工具,它提供了輕量級、非阻塞的并發(fā)控制機制。通過正確使用WaitAsync()Release()方法,配合try...finally確保資源釋放,可以構(gòu)建出高效、穩(wěn)定的異步處理系統(tǒng)。

核心建議

  • 對于HTTP API調(diào)用、數(shù)據(jù)庫訪問等I/O操作,優(yōu)先使用SemaphoreSlim
  • 設(shè)置并發(fā)數(shù)時,考慮目標(biāo)服務(wù)的承受能力和網(wǎng)絡(luò)狀況
  • 配合CancellationToken實現(xiàn)優(yōu)雅的取消操作
  • 在生產(chǎn)環(huán)境中添加適當(dāng)?shù)谋O(jiān)控和日志記錄

正確控制異步并發(fā)不僅能提升應(yīng)用性能,更是構(gòu)建穩(wěn)定、可擴展分布式系統(tǒng)的基石。SemaphoreSlim以其簡潔的API和可靠的行為,成為每個.NET開發(fā)者工具箱中不可或缺的工具。

以上就是C#使用SemaphoreSlim進行并發(fā)控制的最佳實踐的詳細(xì)內(nèi)容,更多關(guān)于C# SemaphoreSlim并發(fā)控制的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C# 位運算符整理

    C# 位運算符整理

    在C#中可以對整型運算對象按位進行邏輯運算。按位進行邏輯運算的意義是:依次取被運算對象的每個位,進行邏輯運算,每個位的邏輯運算結(jié)果是結(jié)果值的每個位。
    2008-10-10
  • C#常用的字符串?dāng)U展方法匯總

    C#常用的字符串?dāng)U展方法匯總

    這篇文章主要介紹了C#常用的字符串?dāng)U展方法匯總,包括了常見的字符串操作與數(shù)據(jù)類型轉(zhuǎn)換等,非常具有實用價值,需要的朋友可以參考下
    2014-10-10
  • 淺談C#數(shù)組(二)

    淺談C#數(shù)組(二)

    上一篇文章我們介紹了C#數(shù)組的一部分,今天來個續(xù)文,關(guān)于C#數(shù)組想要了解更多的請看下面文章的具體內(nèi)容
    2021-09-09
  • 使用C#實現(xiàn)在Excel中創(chuàng)建和配置數(shù)據(jù)透視表

    使用C#實現(xiàn)在Excel中創(chuàng)建和配置數(shù)據(jù)透視表

    在數(shù)據(jù)分析和業(yè)務(wù)報告場景中,數(shù)據(jù)透視表(Pivot?Table)是一種強大的數(shù)據(jù)匯總工具,本文將介紹如何使用?C#?在?Excel?工作表中創(chuàng)建和配置數(shù)據(jù)透視表,感興趣的小伙伴可以了解下
    2026-03-03
  • C#編寫一個控制臺程序的實現(xiàn)串口通信示例

    C#編寫一個控制臺程序的實現(xiàn)串口通信示例

    本文主要介紹了C#編寫一個控制臺程序的實現(xiàn)示例,實現(xiàn)串口通信功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • C#中正則表達式的3種匹配模式

    C#中正則表達式的3種匹配模式

    本文主要介紹在C#中正則匹配的三種模式:單行模式(Singleline)、多行模式(Multiline)與忽略大小寫(IgnoreCase),希望能幫到大家。
    2016-05-05
  • 教你創(chuàng)建一個帶診斷工具的.NET鏡像

    教你創(chuàng)建一個帶診斷工具的.NET鏡像

    本文編寫的初衷是因為在群里有很多小伙伴遇到生產(chǎn)環(huán)境性能問題的時候,.NET的runtime鏡像中沒有帶一些工具,安裝和使用起來很麻煩,所以分享一些我們公司內(nèi)部一些技巧,對.NET鏡像帶診斷工具相關(guān)知識感興趣的朋友一起看看吧
    2022-07-07
  • Unity?UGUI的RawImage原始圖片組件使用示例詳解

    Unity?UGUI的RawImage原始圖片組件使用示例詳解

    這篇文章主要為大家介紹了Unity?UGUI的RawImage原始圖片組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • c#漢諾塔的遞歸算法與解析

    c#漢諾塔的遞歸算法與解析

    c#漢諾塔的遞歸算法與解析,需要的朋友可以參考一下
    2013-03-03
  • 基于WPF實現(xiàn)自定義彈窗輸入功能

    基于WPF實現(xiàn)自定義彈窗輸入功能

    這篇文章主要為大家詳細(xì)介紹了如何基于WPF實現(xiàn)自定義彈窗輸入功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以了解下
    2025-07-07

最新評論

招远市| 即墨市| 天柱县| 遂昌县| 利辛县| 桦川县| 深水埗区| 杨浦区| 临安市| 突泉县| 揭东县| 平南县| 抚顺县| 南宁市| 哈巴河县| 鄂尔多斯市| 开远市| 上杭县| 噶尔县| 蕉岭县| 托克逊县| 台东市| 仙桃市| 馆陶县| 二连浩特市| 改则县| 黔南| 高雄县| 桐庐县| 峨山| 左贡县| 宣化县| 定西市| 永年县| 宜兰县| 元江| 赤壁市| 高密市| 碌曲县| 九江市| 昂仁县|