C#编程学习14:多线程并行程序设计及示例代码(上)

简介: C#编程学习14:多线程并行程序设计及示例代码

所谓并行程序开发是我们不关系任务什么时候执行,只关心怎么利用计算机资源更快的执行。


并行编程是指软件开发的代码,它能在同一时间执行多个计算任务,提高执行效率和性能一种编程方式,属于多线程编程范畴。所以我们在设计过程中一般会将很多任务划分成若干个互相独立子任务,这些任务不考虑互相的依赖和顺序。


NET Framework4.0引入了Task Parallel Library(TPL)实现了基于任务设计而不用处理重复复杂的线程的并行开发框架。它支持数据并行,任务并行与流水线。核心主要是Task,但是一般简单的并行我们可以利用Parallel提供的静态类如下三个方法。


        Parallel.Invoke  对给定任务实现并行开发


        Parallel.For  对固定数目的任务提供循环迭代并行开发


        parallel.Foreach 对固定数目的任务提供循环迭代并行开发


注意:所有的并行开发不是简单的以为只要将For或者Foreach换成Parallel.For与Parallel.Foreach这样简单。


1 For, Foreach和Parallel.For、Parallel.Foreach

1.1 基本分析

for与foreach


相对于原来的for语句foreach具有更好的执行效率


for与Parallel.For区别:


从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个线程使用CPU内核,也就是说可以并行处理程序。For 循环是单线程的,一个线程执行完所有循环。也就说For是同步,Parallel.For 是异步执行。


任务的开销大小对并行任务的影响:


如果任务很小,那么由于并行管理的附加开销(任务分配,调度,同步等成本),可能导致并行执行并不是最优化方案。


Parallel.ForEach 和 ForEach  与 Parallel.For 和 For 一样,一个是异步执行,开辟多个线程。一个是同步执行,开辟一个线程。因此,效率方面同上,主要看执行的什么任务。


Parallel.For不能添加ref或out修饰的变量,错误提示为:不能在匿名表达式、lanmda表达式或查询表达式内使用ref或out变量


停止并行For循环的方法:


在 Parallel.For 或 Parallel.ForEach 循环中,不能使用与顺序循环中相同的 break 或 Exit 语句,这是因为这些语言构造对于循环是有效的,而并行“循环”实际上是方法,不是循环。 相反,可以使用 Stop 或 Break 方法。 Parallel.For 的一些重载接受 Action<int, ParallelLoopState>作为输入参数。 ParallelLoopState 对象由运行时在后台创建,你可以在 lambda 表达式中为它指定你喜欢的任何名称。


在 Action<int, ParallelLoopState>的委托方法中调用ParallelLoopState参数的Stop或Break方法。


Stop 方法;它将告知循环的所有迭代(包括那些在其他线程上的当前迭代之前开始的迭代)在方便的情况下尽快停止。


Break 方法;它会导致其他线程放弃对后续片段的工作(如果它们正忙于任何这样的工作),并在退出循环之前处理完所有前面的元素。


区别就在于,Stop仅仅通知其他迭代尽快结束,而Break不仅通知其他迭代尽快结束,同时还要保证退出之前要完成LowestBreakIteration之前的迭代。 例如,对于从 0 到 1000 并行迭代的 for 循环,如果从第 100 此迭代开始调用 Break,则低于 100 的所有迭代仍会运行,从 101 到 1000 的迭代则不必要。而调用Stop方法不保证低于 100 的所有迭代都会运行。


1.2 示例代码

        public static void test()
        {
            Parallel.For(1, 5, x=>
            {
                Console.WriteLine(x);
            });
            Console.WriteLine("------------------------");
            var numbers = Enumerable.Range(103, 8);
            Parallel.ForEach(numbers, x =>
            {
                Console.WriteLine(x);
            });
            Console.WriteLine("------------------------");
            Parallel.Invoke(
            ()=>{ Console.WriteLine("ABC");},
            ()=>{ Console.WriteLine("xxxOMG");},
            ()=>{ Console.WriteLine("MMG");},
            ()=>{ Console.WriteLine("oooMMG");},
            () => { Console.WriteLine("999ABC"); },
            ()=>{ Console.WriteLine("888MMG");}
            );
        }

运行结果截图:

20200521153011206.png

2 Parallel.Invoke

两个重载方法:

  public static void Invoke(params Action[] actions);  
  public static void Invoke(ParallelOptions parallelOptions, params Action[] actions);

2.1 action调用模式及示例

2.1.1 调用方法解释

//方式一
       Parallel.Invoke(() => Task1(), () => Task2(), () => Task3());
//方式二
       Parallel.Invoke(Task1, Task2, Task3);
//方式三
       Parallel.Invoke(
                () =>
                {
                    Task1();
                },
                Task2,
                delegate () { Task3(); console.write('do someting!');});

2.1.2 示例代码

public class ParallelInvoke
    {
        /// <summary>
        /// Invoke方式一 action
        /// </summary>
        public  void Client1()
        {
            Stopwatch stopWatch = new Stopwatch();
            Console.WriteLine("主线程:{0}线程ID : {1};开始", "Client1", Thread.CurrentThread.ManagedThreadId);
            stopWatch.Start();
            Parallel.Invoke(() => Task1("task1"), () => Task2("task2"), () => Task3("task3"));
            stopWatch.Stop();
            Console.WriteLine("主线程:{0}线程ID : {1};结束,共用时{2}ms", "Client1", Thread.CurrentThread.ManagedThreadId, stopWatch.ElapsedMilliseconds);
        }
        private void Task1(string data)
        {
            Thread.Sleep(5000);
            Console.WriteLine("任务名:{0}线程ID : {1}", data, Thread.CurrentThread.ManagedThreadId);
        }
        private void Task2(string data)
        {
            Console.WriteLine("任务名:{0}线程ID : {1}", data, Thread.CurrentThread.ManagedThreadId);
        }
        private void Task3(string data)
        {
            Console.WriteLine("任务名:{0}线程ID : {1}", data, Thread.CurrentThread.ManagedThreadId);
        }
}

调用:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Diagnostics;
    using System.Threading;
namespace myParallel
{
    class Program
    {
        static void Main(string[] args)
        {
            ParallelInvoke pi = new ParallelInvoke();
            pi.Client1();
        }
    }
}

20200521164648141.png

相关文章
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
548 19
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
547 3
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
911 0
|
监控 算法 C#
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
2696 0
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
412 0
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
439 10
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
1660 12
|
设计模式 C# 图形学
Unity 游戏引擎 C# 编程:一分钟浅谈
本文介绍了在 Unity 游戏开发中使用 C# 的基础知识和常见问题。从 `MonoBehavior` 类的基础用法,到变量和属性的管理,再到空引用异常、资源管理和性能优化等常见问题的解决方法。文章还探讨了单例模式、事件系统和数据持久化等高级话题,旨在帮助开发者避免常见错误,提升游戏开发效率。
879 4
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
866 3

热门文章

最新文章