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

放弃Task.Run!这才是.NET异步编程的正确打开方式

admin
2025年6月18日 21:36 本文热度 28

在.NET中进行异步编程时,许多开发者习惯使用Task.Run将工作卸载到线程池,但这往往不是最佳选择。本文将介绍.NET异步编程的正确方法,帮助你避免常见陷阱并充分发挥异步编程的优势。

关键要点总结

  1. 优先使用内置异步API

    • 大多数.NET库都提供了异步版本的方法(如File.ReadAllTextAsyncHttpClient.GetStringAsync
    • 避免使用Task.Run包装同步方法,这会增加线程池压力并可能导致性能下降
  2. 了解异步操作的适用场景

    • 适用于I/O密集型操作(网络请求、文件读写、数据库查询等)
    • 对于CPU密集型操作,Task.Run可能仍然是合适的选择,但应谨慎使用
  3. 正确处理异步流

    • 使用await foreach处理大型数据集,避免内存溢出
    • 结合EF Core的AsAsyncEnumerable实现高效的数据处理
  4. 并行与并发控制

    • 使用Task.WhenAll并行执行多个独立任务
    • 使用SemaphoreSlim控制并发度,避免资源耗尽
  5. 错误处理与取消机制

    • 始终使用try-catch块捕获异步操作中的异常
    • 使用CancellationToken实现操作取消,提高响应性
  6. UI应用中的异步编程

    • 在UI线程上永远不要阻塞(避免使用.Result.Wait()
    • 使用async/await保持UI的响应性

遵循这些最佳实践,你可以编写出更高效、更可靠的异步代码,充分发挥.NET平台的异步编程能力,同时避免常见的陷阱和性能问题。

using System;using System.IO;using System.Net.Http;using System.Text.Json;using System.Threading;using System.Threading.Tasks;
public static class AsyncBestPractices{    // 1. 使用内置的异步API而非Task.Run    public static async Task<stringDownloadFileAsync(string url)    {        using var client = new HttpClient();        // 正确方式:使用内置的异步方法        return await client.GetStringAsync(url);
        // 错误方式:使用Task.Run包装同步方法        // return await Task.Run(() => client.GetString(url));    }
    // 2. 文件操作的异步模式    public static async Task ProcessFileAsync(string filePath)    {        // 读取文件异步        await using var fileStream = new FileStream(            filePath,             FileMode.Open,             FileAccess.Read,             FileShare.Read,            bufferSize: 4096            useAsync: true); // 确保使用异步I/O
        using var reader = new StreamReader(fileStream);        string content = await reader.ReadToEndAsync();
        // 处理内容        var processedContent = ProcessContent(content);
        // 写回文件异步        await using var outputStream = new FileStream(            filePath + ".processed"            FileMode.Create,             FileAccess.Write,             FileShare.None,            bufferSize: 4096            useAsync: true);
        using var writer = new StreamWriter(outputStream);        await writer.WriteAsync(processedContent);    }
    private static string ProcessContent(string content)    {        // 模拟内容处理        return content.ToUpper();    }
    // 3. 数据库操作的异步模式 (Entity Framework Core)    public static async Task<Order> GetOrderAsync(int orderId)    {        using var context = new OrderDbContext();        // 使用EF Core的异步方法        return await context.Orders.FindAsync(orderId);    }
    // 4. 正确处理异步集合    public static async Task ProcessOrdersAsync()    {        using var context = new OrderDbContext();
        // 流式处理大集合,避免一次性加载全部数据        await foreach (var order in context.Orders.AsAsyncEnumerable())        {            await ProcessOrderAsync(order);        }    }
    private static async Task ProcessOrderAsync(Order order)    {        // 模拟异步处理订单        await Task.Delay(10); // 模拟IO操作        Console.WriteLine($"处理订单: {order.Id}");    }
    // 5. 并行异步操作    public static async Task DownloadMultipleFilesAsync(string[] urls)    {        // 创建所有下载任务        var downloadTasks = urls.Select(url => DownloadAndSaveFileAsync(url));
        // 并行执行所有任务        await Task.WhenAll(downloadTasks);    }
    private static async Task DownloadAndSaveFileAsync(string url)    {        using var client = new HttpClient();        var content = await client.GetStringAsync(url);
        var fileName = Path.GetFileName(url);        await File.WriteAllTextAsync(fileName, content);    }
    // 6. 异步模式中的错误处理    public static async Task SafeDownloadAsync(string url)    {        try        {            using var client = new HttpClient();            var content = await client.GetStringAsync(url);            await ProcessDownloadedContentAsync(content);        }        catch (HttpRequestException ex)        {            Console.WriteLine($"下载失败: {ex.Message}");        }        catch (OperationCanceledException)        {            Console.WriteLine("操作已取消");        }        catch (Exception ex)        {            Console.WriteLine($"发生未知错误: {ex.Message}");        }    }
    private static Task ProcessDownloadedContentAsync(string content)    {        // 处理下载内容        return Task.CompletedTask;    }
    // 7. 异步模式中的CancellationToken使用    public static async Task CancelableOperationAsync(CancellationToken cancellationToken)    {        using var client = new HttpClient();
        try        {            // 支持取消的异步操作            var response = await client.GetAsync("https://example.com", cancellationToken);
            if (response.IsSuccessStatusCode)            {                var content = await response.Content.ReadAsStringAsync(cancellationToken);                Console.WriteLine($"下载完成: {content.Length} 字符");            }        }        catch (OperationCanceledException)        {            Console.WriteLine("操作被用户取消");        }    }
    // 8. 避免在UI线程上阻塞    // 假设这是在WPF/WinForms/UWP应用中    public static async void ButtonClickHandler(object sender, EventArgs e)    {        // 错误方式:在UI线程上等待任务完成        // var result = LongRunningOperation().Result; // 会导致UI卡顿
        // 正确方式:使用await保持UI响应性        await LongRunningOperationAsync();    }
    private static async Task LongRunningOperationAsync()    {        await Task.Delay(5000); // 模拟长时间运行的操作        Console.WriteLine("操作完成");    }
    // 9. 异步流处理 (IAsyncEnumerable)    public static async IAsyncEnumerable<stringReadLinesAsync(string filePath)    {        await using var fileStream = new FileStream(            filePath,             FileMode.Open,             FileAccess.Read,             FileShare.Read,            bufferSize: 4096            useAsync: true);
        using var reader = new StreamReader(fileStream);
        string line;        while ((line = await reader.ReadLineAsync()) != null)        {            yield return line;        }    }
    // 10. 异步模式中的SemaphoreSlim使用    public static async Task ProcessItemsWithThrottleAsync(IEnumerable<string> items, int maxConcurrency = 5)    {        var semaphore = new SemaphoreSlim(maxConcurrency);
        var tasks = items.Select(async item =>        {            await semaphore.WaitAsync();
            try            {                await ProcessItemAsync(item);            }            finally            {                semaphore.Release();            }        });
        await Task.WhenAll(tasks);    }
    private static async Task ProcessItemAsync(string item)    {        await Task.Delay(100); // 模拟处理时间        Console.WriteLine($"处理项: {item}");    }}
// 简单的EF Core上下文示例public class OrderDbContext : DbContext{    public DbSet<Order> Orders { getset; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)    {        optionsBuilder.UseSqlServer("YourConnectionString");    }}
public class Order{    public int Id { getset; }    public string CustomerName { getset; }    public DateTime OrderDate { getset; }}


阅读原文:原文链接


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