c# IO密集型与CPU密集型任务详解,以及在异步编程中的使用示例

发布于:2025-07-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

IO密集型与CPU密集型任务详解(C#示例)

一、基本概念

1. IO密集型任务

IO密集型任务(Input/Output Bound)是指执行过程中大部分时间都在等待输入/输出操作完成的任务。这些任务的特点是CPU计算量相对较小,主要时间花费在磁盘读写、网络通信、数据库访问等IO操作上。

特点:

  • CPU利用率通常较低
  • 性能瓶颈主要在IO设备速度
  • 可通过异步编程或增加IO带宽来提高性能

2. CPU密集型任务

CPU密集型任务(CPU Bound)是指需要大量计算处理的任务,执行时间主要消耗在CPU计算上,而不是等待IO操作。

特点:

  • CPU利用率高(接近100%)
  • 性能瓶颈主要在CPU处理能力
  • 可通过优化算法或增加CPU核心数来提高性能

二、C#示例

1. IO密集型示例

1.1 文件操作异步示例

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task ProcessFileAsync()
    {
        string filePath = "data.txt";
        
        try
        {
            // 异步写入文件
            Console.WriteLine("开始写入文件...");
            await File.WriteAllTextAsync(filePath, "这是异步写入的内容");
            Console.WriteLine("文件写入完成");
            
            // 异步读取文件
            Console.WriteLine("开始读取文件...");
            string content = await File.ReadAllTextAsync(filePath);
            Console.WriteLine($"文件内容: {content}");
            
            // 异步追加内容
            Console.WriteLine("开始追加内容...");
            await File.AppendAllTextAsync(filePath, "\n这是追加的内容");
            Console.WriteLine("内容追加完成");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生错误: {ex.Message}");
        }
    }

    static async Task Main(string[] args)
    {
        await ProcessFileAsync();
    }
}

1.2 网络请求异步示例

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task FetchDataAsync()
    {
        using var client = new HttpClient();
        
        try
        {
            // 异步GET请求
            Console.WriteLine("开始请求数据...");
            string response = await client.GetStringAsync("https://api.example.com/data");
            Console.WriteLine($"获取数据成功,长度: {response.Length}");
            
            // 异步POST请求
            var content = new StringContent("{\"name\":\"value\"}", System.Text.Encoding.UTF8, "application/json");
            Console.WriteLine("开始提交数据...");
            var responseMsg = await client.PostAsync("https://api.example.com/submit", content);
            Console.WriteLine($"提交数据完成,状态码: {responseMsg.StatusCode}");
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"网络请求错误: {ex.Message}");
        }
    }

    static async Task Main(string[] args)
    {
        await FetchDataAsync();
    }
}

1.3 数据库操作异步示例

using System;
using System.Data.SqlClient;
using System.Threading.Tasks;

class Program
{
    static async Task QueryDatabaseAsync()
    {
        string connectionString = "Server=.;Database=TestDB;Integrated Security=True;";
        
        using var connection = new SqlConnection(connectionString);
        await connection.OpenAsync();
        
        // 异步查询
        using var command = new SqlCommand("SELECT * FROM Users WHERE Age > @age", connection);
        command.Parameters.AddWithValue("@age", 20);
        
        Console.WriteLine("开始数据库查询...");
        using var reader = await command.ExecuteReaderAsync();
        
        while (await reader.ReadAsync())
        {
            Console.WriteLine($"用户: {reader["Name"]}, 年龄: {reader["Age"]}");
        }
        
        Console.WriteLine("查询完成");
    }

    static async Task Main(string[] args)
    {
        await QueryDatabaseAsync();
    }
}

2. CPU密集型示例

2.1 基本CPU密集型异步处理

using System;
using System.Threading.Tasks;

class Program
{
    static int CalculatePrimes(int max)
    {
        int count = 0;
        for (int i = 2; i <= max; i++)
        {
            if (IsPrime(i)) count++;
        }
        return count;
    }

    static bool IsPrime(int number)
    {
        if (number <= 1) return false;
        if (number == 2) return true;
        if (number % 2 == 0) return false;

        var boundary = (int)Math.Floor(Math.Sqrt(number));
            
        for (int i = 3; i <= boundary; i += 2)
        {
            if (number % i == 0) return false;
        }
        
        return true;
    }

    static async Task Main(string[] args)
    {
        Console.WriteLine("主线程开始");
        
        // 将CPU密集型任务放到后台线程
        var primeTask = Task.Run(() => CalculatePrimes(1000000));
        
        // 主线程可以继续做其他工作
        Console.WriteLine("主线程继续执行其他工作...");
        await Task.Delay(500); // 模拟其他工作
        
        // 等待计算结果
        int result = await primeTask;
        Console.WriteLine($"计算完成,素数数量: {result}");
    }
}

2.2 并行处理CPU密集型任务

using System;
using System.Linq;
using System.Threading.Tasks;

class Program
{
    static bool IsPrime(int number)
    {
        // 同上省略...
    }

    static async Task<int> ParallelCountPrimesAsync(int max, int partitions)
    {
        // 分割工作范围
        var ranges = Enumerable.Range(0, partitions)
            .Select(i => (start: i * (max / partitions) + 1, 
                         end: (i == partitions - 1) ? max : (i + 1) * (max / partitions)))
            .ToList();
        
        // 并行执行任务
        var tasks = ranges.Select(range => 
            Task.Run(() =>
            {
                int count = 0;
                for (int num = range.start; num <= range.end; num++)
                {
                    if (IsPrime(num)) count++;
                }
                return count;
            }));
        
        // 等待所有任务完成并汇总结果
        var results = await Task.WhenAll(tasks);
        return results.Sum();
    }

    static async Task Main(string[] args)
    {
        Console.WriteLine("开始并行计算...");
        int result = await ParallelCountPrimesAsync(1000000, 4);
        Console.WriteLine($"计算完成,素数数量: {result}");
    }
}

2.3 进度报告和取消支持

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task LongRunningCpuTaskAsync(IProgress<int> progress, CancellationToken cancellationToken)
    {
        for (int i = 0; i <= 100; i++)
        {
            // 检查是否取消
            cancellationToken.ThrowIfCancellationRequested();
            
            // 模拟CPU密集型工作
            await Task.Run(() => 
            {
                // 模拟计算
                for (int j = 0; j < 1000000; j++)
                {
                    var _ = Math.Sqrt(j);
                }
            });
            
            // 报告进度
            progress?.Report(i);
        }
    }

    static async Task Main(string[] args)
    {
        var progress = new Progress<int>(percent => 
            Console.WriteLine($"进度: {percent}%"));
        
        var cts = new CancellationTokenSource();
        
        // 设置5秒后取消
        cts.CancelAfter(5000);
        
        try
        {
            Console.WriteLine("开始长时间CPU任务...");
            await LongRunningCpuTaskAsync(progress, cts.Token);
            Console.WriteLine("任务完成");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("任务已取消");
        }
    }
}

三、处理策略

1. IO密集型任务优化

  • 使用异步编程模型(async/await)
  • 增加IO带宽(更快磁盘、网络)
  • 批量处理减少IO次数
  • 使用缓存减少IO操作

2. CPU密集型任务优化

  • 多线程/并行处理(Parallel类、Task.Run)
  • 优化算法复杂度
  • 使用更高效的库(如Math.NET Numerics)
  • 使用SIMD指令(Vector)

混合示例(并行处理CPU密集型任务)

using System;
using System.Threading.Tasks;

class Program
{
    static bool IsPrime(int number)
    {
        // 同上省略...
    }

    static async Task Main(string[] args)
    {
        // 并行计算素数(CPU密集型)
        int max = 1000000;
        int segmentSize = max / 4;
        
        var tasks = new Task<int>[4];
        for (int i = 0; i < 4; i++)
        {
            int start = i * segmentSize + 1;
            int end = (i == 3) ? max : (i + 1) * segmentSize;
            
            tasks[i] = Task.Run(() => 
            {
                int count = 0;
                for (int num = start; num <= end; num++)
                {
                    if (IsPrime(num)) count++;
                }
                return count;
            });
        }
        
        await Task.WhenAll(tasks);
        
        int totalPrimes = 0;
        foreach (var task in tasks)
        {
            totalPrimes += task.Result;
        }
        
        Console.WriteLine($"并行计算100万以内素数总数: {totalPrimes}");
    }
}
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task ProcessDataAsync(string inputFile, string outputFile)
    {
        // IO密集型:异步读取文件
        Console.WriteLine("开始读取文件...");
        string content = await File.ReadAllTextAsync(inputFile);
        
        // CPU密集型:处理数据(转移到后台线程)
        Console.WriteLine("开始处理数据...");
        string processedContent = await Task.Run(() => ProcessContent(content));
        
        // IO密集型:异步写入结果
        Console.WriteLine("开始写入结果...");
        await File.WriteAllTextAsync(outputFile, processedContent);
        
        Console.WriteLine("处理完成");
    }

    static string ProcessContent(string content)
    {
        // 模拟CPU密集型处理
        var charArray = content.ToCharArray();
        for (int i = 0; i < charArray.Length; i++)
        {
            if (i % 2 == 0)
            {
                charArray[i] = char.ToUpper(charArray[i]);
            }
            else
            {
                charArray[i] = char.ToLower(charArray[i]);
            }
        }
        return new string(charArray);
    }

    static async Task Main(string[] args)
    {
        await ProcessDataAsync("input.txt", "output.txt");
    }
}

四、总结

  1. IO密集型:主要时间花费在等待IO操作,应关注IO优化和异步编程
  2. CPU密集型:主要时间花费在计算,应关注算法优化和多核利用
  3. 实际应用:很多任务是混合型的,需要根据瓶颈采取相应策略
  4. C#特性:充分利用async/await、Task、Parallel等特性处理不同类型任务

网站公告

今日签到

点亮在社区的每一天
去签到