设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间21 现在时间21 缓存数据 青春之所以让人留念,是因为我们年轻时干的蠢事大都妙不可言。晚安!

青春之所以让人留念,是因为我们年轻时干的蠢事大都妙不可言。晚安!

查看: 627|回复: 0

C#中高效的多线程并行处理实现方式详解

[复制链接]

  离线 

TA的专栏

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 打卡月天数:0
  • 打卡总奖励:70
  • 最近打卡:2025-06-04 01:46:07
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
26
主题
20
精华
0
金钱
149
积分
52
注册时间
2023-9-30
最后登录
2025-6-4

发表于 2025-6-1 05:33:32 | 显示全部楼层 |阅读模式
前言

在处理大型数据集时,单线程处理往往成为性能瓶颈。通过将数据分割成多个小块,并利用多线程进行并行处理,可以显著提升程序的执行效率和响应速度。
本文将详细介绍几种高效的多线程并行处理实现方式,帮助开发者优化数据处理流程。

使用Parallel.ForEach进行并行处理

最简单的实现方式是使用C#内置的
  1. Parallel.ForEach
复制代码
方法。
  1. namespace AppParallel
  2. {
  3.     internal class Program
  4.     {
  5.         static object lockObject =
  6.         new object();
  7.         static void Main(string[] args)
  8.         {
  9.             // 创建示例数据
  10.             var largeList =
  11.             Enumerable.Range(1, 1000000).ToList();

  12.             // 设置并行选项
  13.             var parallelOptions = new ParallelOptions
  14.             {
  15.                 MaxDegreeOfParallelism =
  16.                 Environment.ProcessorCount
  17.                 // 使用处理器核心数量的线程
  18.             };

  19.             try
  20.             {
  21.                 Parallel.ForEach(largeList, parallelOptions,
  22.                 (number) =>
  23.                 {
  24.                     // 这里是对每个元素的处理逻辑
  25.                     var result = ComplexCalculation(number);

  26.                     // 注意:如果需要收集结果,要考虑线程安全
  27.                     lock (lockObject)
  28.                     {
  29.                         // 进行线程安全的结果收集
  30.                         Console.WriteLine(result);
  31.                     }
  32.                 });
  33.             }
  34.             catch (AggregateException ae)
  35.             {
  36.                 // 处理并行处理中的异常
  37.                 foreach (var ex in
  38.                 ae.InnerExceptions)
  39.                 {
  40.                     Console.WriteLine($"Error:
  41.                     {ex.Message}");
  42.                 }
  43.             }
  44.         }
  45.         private static int
  46.         ComplexCalculation(int number)
  47.         {
  48.             // 模拟复杂计算
  49.             Thread.Sleep(100);
  50.             return number * 2;
  51.         }

  52.     }
  53. }
复制代码
1.webp


手动分块处理方式

有时我们需要更精细的控制,可以手动将数据分块并分配给不同的线程。
  1. namespace AppParallel
  2. {
  3.     internal class Program
  4.     {
  5.         static void Main(string[] args)
  6.         {
  7.             var largeList = Enumerable.Range(1, 1000000).ToList();
  8.             ProcessByChunks(largeList, 1000);
  9.             // 每1000个元素一个块
  10.         }
  11.         public static void ProcessByChunks<T>(List<T> largeList,
  12.         int chunkSize)
  13.         {
  14.             // 计算需要多少个分块
  15.             int chunksCount = (int)Math.Ceiling((double)largeList.Count / chunkSize);
  16.             var tasks = new List<Task>();

  17.             for (int i = 0; i < chunksCount; i++)
  18.             {
  19.                 // 获取当前分块的数据
  20.                 var chunk = largeList
  21.                     .Skip(i * chunkSize)
  22.                     .Take(chunkSize)
  23.                     .ToList();

  24.                 // 创建新任务处理当前分块
  25.                 var task = Task.Run(() => ProcessChunk(chunk));
  26.                 tasks.Add(task);
  27.             }

  28.             // 等待所有任务完成
  29.             Task.WaitAll(tasks.ToArray());
  30.         }

  31.         private static void
  32.         ProcessChunk<T>(List<T> chunk)
  33.         {
  34.             foreach (var item in chunk)
  35.             {
  36.                 // 处理每个元素
  37.                 ProcessItem(item);
  38.             }
  39.         }

  40.         private static void
  41.         ProcessItem<T>(T item)
  42.         {
  43.             // 具体的处理逻辑
  44.             Console.WriteLine
  45.             ($"Processing item: {item} on thread: {Task.CurrentId}");
  46.         }

  47.     }
  48. }
复制代码
2.webp


使用生产者-消费者模式

对于更复杂的场景,我们可以使用生产者-消费者模式,这样可以更好地控制内存使用和处理流程。
  1. public class ProducerConsumerExample
  2. {
  3.     private readonly BlockingCollection<int> _queue;
  4.     private readonly
  5.     int _producerCount;
  6.     private readonly
  7.     int _consumerCount;
  8.     private readonly
  9.     CancellationTokenSource _cts;

  10.     public ProducerConsumerExample(int queueCapacity = 1000)
  11.     {
  12.         _queue = new BlockingCollection<int>(queueCapacity);
  13.         _producerCount = 1;
  14.         _consumerCount =
  15.         Environment.ProcessorCount;
  16.         _cts = new CancellationTokenSource();
  17.     }

  18.     public async Task ProcessDataAsync(List<int> largeList)
  19.     {
  20.         // 创建生产者任务
  21.         var producerTask =
  22.         Task.Run(() => Producer(largeList));

  23.         // 创建消费者任务
  24.         var consumerTasks = Enumerable.Range(0, _consumerCount)
  25.             .Select(_ => Task.Run(() => Consumer()))
  26.             .ToList();

  27.         // 等待所有生产者完成
  28.         await producerTask;

  29.         // 标记队列已完成
  30.         _queue.CompleteAdding();

  31.         // 等待所有消费者完成
  32.         await Task.WhenAll(consumerTasks);
  33.     }

  34.     private void Producer(List<int> items)
  35.     {
  36.         try
  37.         {
  38.             foreach (var item in items)
  39.             {
  40.                 if (_cts.
  41.                 Token.IsCancellationRequested)
  42.                     break;

  43.                 _queue.Add(item);
  44.             }
  45.         }
  46.         catch (Exception ex)
  47.         {
  48.             Console.WriteLine($"Producer error:
  49.             {ex.Message}");
  50.             _cts.Cancel();
  51.         }
  52.     }

  53.     private void Consumer()
  54.     {
  55.         try
  56.         {
  57.             foreach (var item in _queue.GetConsumingEnumerable())
  58.             {
  59.                 if (_cts.Token.IsCancellationRequested)
  60.                     break;

  61.                 // 处理数据
  62.                 ProcessItem(item);
  63.             }
  64.         }
  65.         catch (Exception ex)
  66.         {
  67.             Console.WriteLine($"Consumer error: {ex.Message}");
  68.             _cts.Cancel();
  69.         }
  70.     }

  71.     private void ProcessItem(int item)
  72.     {
  73.         // 具体的处理逻辑
  74.         Thread.Sleep(100);
  75.         // 模拟耗时操作
  76.         Console.WriteLine($"Processed item {item} on thread {Task.CurrentId}");
  77.     }
  78. }

  79. // 使用示例
  80. static async Task Main(string[] args)
  81. {
  82.     var processor = new ProducerConsumerExample();
  83.     var largeList = Enumerable.Range(1, 10000).ToList();
  84.     await processor.ProcessDataAsync(largeList);
  85. }
复制代码
3.webp


注意事项

1、合适的分块大小:分块不宜过小,因为过多的线程切换会抵消并行处理的优势;也不宜过大,以免影响负载均衡。建议从每块1000到5000个元素开始测试,找到最优的分块大小。
2、异常处理:务必妥善处理并行处理中的异常情况。每个任务应使用try-catch语句包装,确保异常不会导致整个程序崩溃。同时,考虑使用CancellationToken来优雅地终止所有任务。
3、资源管理:注意内存使用,避免一次性加载过多数据。合理控制并发线程的数量,通常不超过处理器核心数的两倍。对于实现了IDisposable接口的资源,使用using语句进行管理,确保资源及时释放。
4、线程安全:访问共享资源时必须保证线程安全,可以使用适当的同步机制如锁(lock)、信号量(Semaphore)等。考虑使用线程安全的集合类,例如ConcurrentDictionary或ConcurrentQueue。避免过度锁定,以免造成性能瓶颈。
通过遵循这些注意事项,可以确保在C#中高效且安全地进行大数据列表的并行处理。

总结

并行处理大数据列表是提升程序性能的有效手段,但需根据具体场景选择合适的实现方式。
本文介绍了三种主要方法,各有其适用场景和优势:
Parallel.ForEach:适用于简单场景,易于实现且代码简洁。适合快速原型开发或处理逻辑较为直接的任务。
手动分块处理:提供更精细的控制,适合中等复杂度场景。允许开发者优化分块大小和线程分配,以达到最佳性能。
生产者-消费者模式:适用于复杂场景,能够更好地管理资源使用和任务调度。特别适合需要高效处理大量数据流或涉及多个处理阶段的应用。
在实际应用中,建议首先进行性能测试,根据数据量大小、处理复杂度以及系统的硬件配置选择最合适的实现方式。
另外,务必重视异常处理和资源管理,确保程序的稳定性和可靠性。通过合理的并行处理策略,可以显著提高大型数据集的处理效率,为应用程序带来更好的用户体验。
以上就是C#中高效的多线程并行处理实现方式详解的详细内容,更多关于C#多线程并行处理的资料请关注晓枫资讯其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表