狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

避免在C#循環(huán)中使用await

admin
2024年10月3日 0:2 本文熱度 688

在C#中,異步編程因其能夠提升應(yīng)用程序性能和響應(yīng)能力而變得越來(lái)越流行。asyncawait關(guān)鍵字使得編寫異步代碼變得更加容易,但如果使用不當(dāng),它們也可能引入一些陷阱。一個(gè)常見(jiàn)的錯(cuò)誤是在循環(huán)中使用await,這可能導(dǎo)致性能瓶頸和意外行為。在本文中,我們將探討為什么應(yīng)該避免在C#循環(huán)中使用await,并討論一些更高效地處理異步操作的替代方法。

在循環(huán)中使用await的問(wèn)題

順序執(zhí)行

當(dāng)在循環(huán)中使用await時(shí),每次迭代都會(huì)等待前一次迭代完成后再開(kāi)始。這導(dǎo)致了順序執(zhí)行,抵消了異步編程的好處。請(qǐng)看以下示例:

foreach (var item in items){    await ProcessItemAsync(item);}

在這段代碼中,每次迭代都會(huì)等待ProcessItemAsync完成后再進(jìn)行下一次迭代。如果ProcessItemAsync需要較長(zhǎng)時(shí)間才能完成,這會(huì)導(dǎo)致性能不佳。

示例場(chǎng)景

假設(shè)我們需要通過(guò)異步下載處理一組URL的內(nèi)容。在循環(huán)中使用await的代碼如下:

foreach (var url in urls){    var content = await DownloadContentAsync(url);    ProcessContent(content);}

在這種情況下,每個(gè)URL都是一個(gè)接一個(gè)地處理,導(dǎo)致總執(zhí)行時(shí)間是所有單個(gè)下載時(shí)間的總和。如果我們有10個(gè)URL,每個(gè)下載需要1秒,總執(zhí)行時(shí)間將大約是10秒。

資源爭(zhēng)用

在循環(huán)中使用await還可能導(dǎo)致資源爭(zhēng)用。每次迭代都會(huì)占用資源(如內(nèi)存和網(wǎng)絡(luò)連接)直到等待的任務(wù)完成。這可能導(dǎo)致可用資源的耗盡,尤其是在處理大量任務(wù)時(shí)。

更好的替代方法

使用Task.WhenAll

為了并發(fā)執(zhí)行異步操作,我們可以使用Task.WhenAll。這種方法允許我們一次啟動(dòng)所有異步任務(wù),并等待它們?nèi)客瓿?。以下是如何重寫前面的示例?/p>

static async Task Main(string[] args){    var urls = new List<string>{    "https://www.163.com",    "https://www.microsoft.com",    "https://www.baidu.com"};
   var downloadTasks = urls.Select(url => DownloadContentAsync(url)).ToArray();    var contents = await Task.WhenAll(downloadTasks);
   foreach (var content in contents)    {        ProcessContent(content);    }}
static async Task<string> DownloadContentAsync(string url){    using (var client = new HttpClient())    {        client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
       var response = await client.GetAsync(url);        response.EnsureSuccessStatusCode();        return await response.Content.ReadAsStringAsync();    }}
static void ProcessContent(string content){    Console.WriteLine($"Processing content of length: {content.Length}");    // 這里可以添加更多的內(nèi)容處理邏輯  }

?

在這個(gè)版本中,所有下載任務(wù)同時(shí)啟動(dòng),我們等待它們?nèi)客瓿珊笤偬幚斫Y(jié)果。這種方法顯著減少了總執(zhí)行時(shí)間,因?yàn)槿蝿?wù)是并行運(yùn)行的。

使用Parallel.ForEachAsync

C#還提供了Parallel.ForEachAsync,它允許你在不阻塞主線程的情況下并行運(yùn)行異步操作:

await Parallel.ForEachAsync(urls, async (url, cancellationToken) =>{    var content = await DownloadContentAsync(url);    ProcessContent(content);});

Parallel.ForEachAsync確保多個(gè)迭代可以并發(fā)運(yùn)行,提升性能的同時(shí)保持代碼的簡(jiǎn)潔和可讀性。

限制并發(fā)

在某些情況下,運(yùn)行過(guò)多的并發(fā)任務(wù)可能會(huì)使系統(tǒng)資源不堪重負(fù)。我們可以通過(guò)使用SemaphoreSlim來(lái)限制并發(fā)級(jí)別:

internal class Program{    static readonly HttpClient client = new HttpClient();    static readonly SemaphoreSlim semaphore = new SemaphoreSlim(5); // 限制并發(fā)任務(wù)數(shù)為5  
   static async Task Main(string[] args)    {        List<string> urls = new List<string>    {        "https://www.163.com",        "https://www.baidu.com",        "https://www.microsoft.com"    };
       var tasks = urls.Select(async url =>        {            await semaphore.WaitAsync();            try            {                var content = await DownloadContentAsync(url);                ProcessContent(content);            }            finally            {                semaphore.Release();            }        }).ToArray();
       await Task.WhenAll(tasks);
       Console.WriteLine("所有任務(wù)已完成");    }
   static async Task<string> DownloadContentAsync(string url)    {        client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");        var response = await client.GetAsync(url);        response.EnsureSuccessStatusCode();        return await response.Content.ReadAsStringAsync();    }
   static void ProcessContent(string content)    {        Console.WriteLine($"處理內(nèi)容,長(zhǎng)度: {content.Length}");        // 在這里添加處理內(nèi)容的邏輯      }}

這種方法限制了并發(fā)任務(wù)的數(shù)量,更有效地管理資源使用。

結(jié)論

雖然await是C#異步編程的強(qiáng)大工具,但在循環(huán)中使用它可能導(dǎo)致性能不佳和資源爭(zhēng)用。通過(guò)理解順序執(zhí)行的影響,并利用Task.WhenAll、Parallel.ForEachAsyncSemaphoreSlim等替代方法,我們可以編寫更高效和健壯的異步代碼。避免在循環(huán)中使用await并采用更好的模式將提升你的應(yīng)用程序性能,使代碼更易維護(hù)和擴(kuò)展。遵循這些最佳實(shí)踐,你可以充分利用C#異步編程的潛力。


該文章在 2024/10/3 12:23:59 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved