• 多核时代 .NET Framework 4 中的并行编程2任务并行库之Task (上)


    1.     任务并行库

    任务并行库 (Task Parallel Library) 是 .NET Framework 4 版的 System.Threading System.Threading.Tasks 命名空间中的一组公共类型和 API。 TPL 的目的在于简化向应用程序中添加并行性和并发性的过程,从而提高开发人员的工作效率。TPL 会动态地按比例调节并发程度,以便最有效地使用所有可用的处理器。 此外,TPL 还处理工作分区、ThreadPool 上的线程调度、取消支持、状态管理以及其他低级别的细节操作。 通过使用 TPL,您可以在将精力集中于程序要完成的工作,同时最大程度地提高代码的性能。

    .NET Framework 4 开始,TPL 是编写多线程代码和并行代码的首选方法。 但是,并不是所有代码都适合并行化;例如,如果某个循环在每次迭代时只执行少量工作,或它在很多次迭代时都不运行,那么并行化的开销可能导致代码运行更慢。 此外,像任何多线程代码一样,并行化会增加程序执行的复杂性。 尽管 TPL 简化了多线程方案,但我们建议您对线程处理概念(例如,锁、死锁和争用条件)进行基本的了解,以便能够有效地使用 TPL。

    下面,将介绍并行库中一个重要的类:Task.它表示一个异步操作.

    2.     Task基本使用:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace AppParallel

    {

        class Program

        {

            static void Main(string[] args)

            {

                Task task1 = new Task(new Action(SayHello));

     

                Task task2 = new Task(delegate

                    {

                        SayHello();

                    });

                Task task3 = new Task(() => SayHello());

     

                Task task4 = new Task(() =>

                {

                    SayHello();

                });

                task1.Start();

                task2.Start();

                task3.Start();

                task4.Start();

               

                Console.WriteLine("Main 执行完毕!");

                Console.ReadLine();

     

            }

     

            static void SayHello()

            {

                Console.WriteLine("Hello C# Parallel!");

            }

        }

    }

     

    上面的例子中,我们首先需要引用System.Threading.Tasks名空间,这个命名空间是.Net4中新增加的.同时,我们可以编写并行代码很简单,需要申明一个Task的实例,然后调用他的Start()方法即可.

    Task类的提供以下构造函数:

    (1)           Task(Action) 

    使用指定的操作初始化新的 Task。  

    (2)           Task(Action, CancellationToken) 

    用指定的操作和 CancellationToken 初始化新的 Task 

    (3)           Task(Action, TaskCreationOptions) 

    使用指定的操作和创建选项初始化新的 Task 

    (4)           Task(Action<Object>, Object) 

    使用指定的操作和状态初始化新的 Task 

    (5)           Task(Action, CancellationToken, TaskCreationOptions) 

    使用指定的操作和创建选项初始化新的 Task

    (6)           Task(Action<Object>, Object, CancellationToken) 

    使用指定的操作、状态和选项初始化新的 Task 

    (7)           Task(Action<Object>, Object, TaskCreationOptions) 

    使用指定的操作、状态和选项初始化新的 Task 

    (8)           Task(Action<Object>, Object, CancellationToken, TaskCreationOptions) 

    使用指定的操作、状态和选项初始化新的 Task

    其中,TaskCreationOptions用来指定可控制任务的创建和执行的可选行为的标志。可用的枚举如下:

    Ø None 指定应使用默认行为。 

    Ø PreferFairness 提示 TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。 

    Ø LongRunning 指定某个任务将是运行时间长、粗粒度的操作。 它会向 TaskScheduler 提示,过度订阅可能是合理的。 

    Ø AttachedToParent 指定将任务附加到任务层次结构中的某个父级。 

    3.     传入参数

    编写代码传递参数是常见的,那么在Task中如何将参数传入在执行的代码中呢?此时,我们需要使用Task的Task(Action<Object>, Object)这个构造函数.例子如下:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading;

    using System.Threading.Tasks;

    namespace AppParallel

    {

        class Program

        {

            static void Main(string[] args)

            {

                Task task1 = new Task(new Action<object>(DisplayTime), DateTime.Now);

     

                Task task2 = new Task(delegate(object obj)

                    {

                        DisplayTime(obj);

                    }, DateTime.Now);

     

                Task task3 = new Task((obj) => DisplayTime(obj), DateTime.Now);

     

                Task task4 = new Task((obj) =>

                {

                    DisplayTime(obj);

                }, DateTime.Now);

     

                task1.Start();

                task2.Start();

                task3.Start();

                task4.Start();

     

                Console.WriteLine("执行完毕!");

                Console.ReadLine();

     

            }

     

            static void DisplayTime(object dt)

            {

                Console.WriteLine("现在时间是:" + ((DateTime)dt).ToLocalTime());

            }

        }

    }

    4.     返回结果

    我们可以通过Task<T>实例的Result来获取代码执行的返回结果,其中T表示返回结果的类型,例子:

     static void Main(string[] args)

     {

     

               Task<bool> t = new Task<bool>(Contains, "xzdf2a");

                t.Start();

                Console.WriteLine("Main执行完毕!");

                Console.WriteLine("Task返回的结果:" + t.Result.ToString());

                Console.ReadLine();

     }

    static bool Contains(object obj)

        {

                string s = obj as string;

                if (s != null)

                {

                    return s.Contains('a');

                }

                return false;

     }

     

     
         本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    原文链接:http://www.cnblogs.com/xray2005/archive/2011/08/21/2147625.html
  • 相关阅读:
    洛谷P4382 [八省联考2018]劈配(网络流,二分答案)
    洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)
    C++实用整数快速输入输出模板(C++)
    洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)
    洛谷P4338 [ZJOI2018]历史(LCT,树形DP,树链剖分)
    洛谷P3613 睡觉困难综合征(LCT,贪心)
    洛谷P3960 列队(NOIP2017)(Splay)
    洛谷P3275 [SCOI2011]糖果(差分约束,最长路,Tarjan,拓扑排序)
    博弈论总结(只会打表,永不证明)(博弈论)
    洛谷P1450 [HAOI2008]硬币购物(背包问题,容斥原理)
  • 原文地址:https://www.cnblogs.com/xwj517537691/p/3127033.html
Copyright © 2020-2023  润新知