LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

避免在C#循环中使用await

admin
2024年10月3日 0:2 本文热度 302

在C#中,异步编程因其能够提升应用程序性能和响应能力而变得越来越流行。asyncawait关键字使得编写异步代码变得更加容易,但如果使用不当,它们也可能引入一些陷阱。一个常见的错误是在循环中使用await,这可能导致性能瓶颈和意外行为。在本文中,我们将探讨为什么应该避免在C#循环中使用await,并讨论一些更高效地处理异步操作的替代方法。

在循环中使用await的问题

顺序执行

当在循环中使用await时,每次迭代都会等待前一次迭代完成后再开始。这导致了顺序执行,抵消了异步编程的好处。请看以下示例:

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

在这段代码中,每次迭代都会等待ProcessItemAsync完成后再进行下一次迭代。如果ProcessItemAsync需要较长时间才能完成,这会导致性能不佳。

示例场景

假设我们需要通过异步下载处理一组URL的内容。在循环中使用await的代码如下:

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

在这种情况下,每个URL都是一个接一个地处理,导致总执行时间是所有单个下载时间的总和。如果我们有10个URL,每个下载需要1秒,总执行时间将大约是10秒。

资源争用

在循环中使用await还可能导致资源争用。每次迭代都会占用资源(如内存和网络连接)直到等待的任务完成。这可能导致可用资源的耗尽,尤其是在处理大量任务时。

更好的替代方法

使用Task.WhenAll

为了并发执行异步操作,我们可以使用Task.WhenAll。这种方法允许我们一次启动所有异步任务,并等待它们全部完成。以下是如何重写前面的示例:

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}");    // 这里可以添加更多的内容处理逻辑  }

?

在这个版本中,所有下载任务同时启动,我们等待它们全部完成后再处理结果。这种方法显著减少了总执行时间,因为任务是并行运行的。

使用Parallel.ForEachAsync

C#还提供了Parallel.ForEachAsync,它允许你在不阻塞主线程的情况下并行运行异步操作:

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

Parallel.ForEachAsync确保多个迭代可以并发运行,提升性能的同时保持代码的简洁和可读性。

限制并发

在某些情况下,运行过多的并发任务可能会使系统资源不堪重负。我们可以通过使用SemaphoreSlim来限制并发级别:

internal class Program{    static readonly HttpClient client = new HttpClient();    static readonly SemaphoreSlim semaphore = new SemaphoreSlim(5); // 限制并发任务数为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("所有任务已完成");    }
   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($"处理内容,长度: {content.Length}");        // 在这里添加处理内容的逻辑      }}

这种方法限制了并发任务的数量,更有效地管理资源使用。

结论

虽然await是C#异步编程的强大工具,但在循环中使用它可能导致性能不佳和资源争用。通过理解顺序执行的影响,并利用Task.WhenAllParallel.ForEachAsyncSemaphoreSlim等替代方法,我们可以编写更高效和健壮的异步代码。避免在循环中使用await并采用更好的模式将提升你的应用程序性能,使代码更易维护和扩展。遵循这些最佳实践,你可以充分利用C#异步编程的潜力。


该文章在 2024/10/3 12:23:59 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved