4.0中的并行计算和多线程详解(二)

  相关文章:4.0中的
并行计算和多线程详解(一)  多线程部分

  多线程在4.0中被简化了很多,仅仅只需要用到System.Threading.Tasks.::.Task类,下面就来详细介绍下Task类的使用。

  一、简单使用

  开启一个线程,执行循环方法,返回结果。开始线程为Start(),等待线程结束为Wait()。

Code         /// <summary>         /// Task简单使用         /// </summary>         private void Demo1()         {             int i = 0;             Random r = new Random(DateTime.Now.Second);             Task t = new Task(() =>             {                 for (int v = 0; v < 100; v++)                     i += r.Next(100);             });             t.Start();             t.Wait();            
Console.WriteLine("这是执行Task1后等待完成:" + i.ToString());             Console.ReadLine();         }

  比以前使用Thread方便多了吧。上面的例子是使用外部的变量获得结果,下面的例子是用Task<T>直接返回结果,当调用Result属性时,会自动等待线程结束,等同调用了Wait()。代码如下:

Code         /// <summary>         /// Task带返回值         /// </summary>         private void Demo2()         {             Random r = new Random(DateTime.Now.Second);             Task<int> t = new Task<int>(() =>             {                 int i = 0;                 for (int v = 0; v < 100; v++)                     i += r.Next(100);                 return i;             });             t.Start();             Console.WriteLine("这是执行Task1
获取返回值:" + t.Result.ToString());             Console.ReadLine();         }

  总结1:Task的使用比Thread简单很多,减少了同步,等待等等问题,唯一的遗憾是不支持Thread的IsBackground。

  结论1:如果不需要使用IsBackground,那么尽情的使用Task吧。

  二、线程执行完毕后调用另一个线程

  也就是两个线程,有序的执行,这里使用ContinueWith(),t执行完毕后再执行一个task方法,不多说了代码如下:

Code         /// <summary>         /// Task 执行完毕后调用另一个Task         /// </summary>         private void Demo3()         {             Random r = new Random(DateTime.Now.Second);             Task<int> t = new Task<int>(() =>             {                 int i = 0;                 for (int v = 0; v < 100; v++)                     i += r.Next(100);                 return i;             });             t.ContinueWith((Task<int> task) =>             {                 Console.WriteLine("这是执行完毕Task1后继续调用Task2:" + task.Result.ToString());             });             t.Start();             Console.ReadLine();         }

  也可以直接链式的写下去,代码如下:

Code         /// <summary>         /// Task 执行完毕后调用另一个Task(链式写法)         /// </summary>         private void Demo4()         {             Random r = new Random(DateTime.Now.Second);             Task<int> t = new Task<int>(() =>             {                 int i = 0;                 for (int v = 0; v < 100; v++)                     i += r.Next(100);                 return i;             });             Task t2 = t.ContinueWith((Task<int> task) =>             {                 Console.WriteLine(task.Result.ToString());             });             t2.ContinueWith(task =>             {                 Console.WriteLine("这是执行完毕Task1后继续调用Task2,Task2后调用Task3。");             });             t.Start();             Console.ReadLine();         }

  结论2:Task可以便捷的将几个方法串行执行。

  三、带有父子关系的线程/多线程并行开启

  t带有t1,t2,t3三个子线程,执行t的时候t1,t2,t3可并行处理,t必须等待t1,t2,t3都执行完毕后才能结束。创建子Task时候必须指定参数为AttachedToParent。

Code         /// <summary>         /// 带有父子关系的Task集合,[TaskCreationOptions.AttachedToParent]         ///         /// 值                说明         ///
None              默认值,此Task会被排入Local Queue中等待执行,采用LIFO模式。         /// AttachedToParent  建立的Task必须是外围的Task的子Task,也是放入Local Queue,LIFO模式。         /// LongRunning       建立的Task不受Thread Pool所管理,直接新增一个Thread来执行此Task,无等待、无排程。         /// PreferFairness    建立的Task直接放入Global Queue中,FIFO模式。(比上面的优先级低)         /// </summary>         private void Demo5()         {             Task<int> t = new Task<int>(() =>             {                 Task<int> t1 = new Task<int>(() =>                 {                     int i = 0;                     Random r = new Random(DateTime.Now.Second);                     for (int v = 0; v < 100; v++)                         i += r.Next(100);                     return i;                 }, TaskCreationOptions.AttachedToParent);                 Task<int> t2 = new Task<int>(() =>                 {                     int i = 0;                     Random r = new Random(DateTime.Now.Second);                     for (int v = 0; v < 100; v++)                         i += r.Next(100);                     return i;                 }, TaskCreationOptions.AttachedToParent);                 Task<int> t3 = new Task<int>(() =>                 {                     int i = 0;                     Random r = new Random(DateTime.Now.Second);                     for (int v = 0; v < 100; v++)                         i += r.Next(100);                     return i;                 }, TaskCreationOptions.AttachedToParent);                 t1.Start();                 t2.Start();                 t3.Start();                 return t1.Result + t2.Result + t3.Result;             });             t.Start();             t.Wait();             Console.WriteLine("这是带有父子关系的Task集合:" + t.Result.ToString());             Console.ReadLine();         }

  结论3:多个线程的同时开启在这里也很方便,也不用担心同步等问题。

  四、Task的中断

  这个很复杂,就不多说了,代码中有比较详细的介绍。

Code         /// <summary>         /// 中途取消Task执行,Token         ///         /// 一是正常结束、二是产生例外、三是
透过Cancel机制,这三种情况都会反映在Task.
Status属性上         /// 值                              说明         /// Created                         Task已经建立,但未呼叫Start。         /// WaitingForActivation            Task已排入排程,但尚未执行(一般我们建立的Task不会有此状态,只有ContinueWith所产生的Task才会有此状态)。         /// WaitingToRun                    Task已排入排程,等待执行中。         /// Running                         Task执行中。         /// WaitingForChildrenToComplete    Task正等待子Task束。         /// RanToCompletion                 Task已经正常执行完毕。         /// Canceled                        Task已被取消。         /// Faulted                         Task执行中发生未预期例外。         ///         /// 除了Status属性外,Task还提供了另外三个属性来判定Task状态。         /// 属性            说明         /// IsCompleted     Task已经正常执行完毕。         /// IsFaulted       Task执行中法生未预期例外。         /// IsCanceled      Task已被取消。         /// </summary>         private void Demo6()         {             CancellationTokenSource cts = new CancellationTokenSource();             var c
token = cts.Token;             Task t1 = new Task(() =>             {                 for (int v = 0; v < 10; v++)                 {                     if (ctoken.IsCancellationRequested)                     {                         //第一种写法

时间: 2024-10-23 03:19:12

4.0中的并行计算和多线程详解(二)的相关文章

一起谈.NET技术,4.0中的并行计算和多线程详解(二)

相关文章:4.0中的并行计算和多线程详解(一) 多线程部分 多线程在4.0中被简化了很多,仅仅只需要用到System.Threading.Tasks.::.Task类,下面就来详细介绍下Task类的使用. 一.简单使用 开启一个线程,执行循环方法,返回结果.开始线程为Start(),等待线程结束为Wait(). Code         /// <summary>         /// Task简单使用         /// </summary>         private

4.0中的并行计算和多线程详解(一)

并行计算部分 沿用微软的写法,System.Threading.Tasks.::.Parallel类,提供对并行循环和区域的支持. 我们会用到的方法有For,ForEach,Invoke. 一.简单使用 首先我们初始化一个List用于循环,这里我们循环10次.(后面的代码都会按这个标准进行循环) Code             Program.Data = new List<int>();             for (int i = 0; i < 10; i++)        

jQuery3.0中的buildFragment私有函数详解_jquery

时隔 3 个月,jQuery 团队终于发布了 3.0 Alpha 版本.有两个版本 jQuery compat 3.0 和 jQuery 3.0. jQuery compat 3.0 对应之前的 1.x, 兼容更多的浏览器,对于IE支持到 8.0 版本 jQuery 3.0 对应之前的 2.x,关注更新的浏览器,对于IE支持到 9.0 版本 此外, 3.0还增加了对 Yandex 浏览器的支持,一款来自俄罗斯的浏览器. 下面看下jQuery3.0中的buildFragment. 在 jQuery

解析.Net 4.0 中委托delegate的使用详解_实用技巧

.Net中的委托从功能上讲和c语言或者c++中的方法指针类似,可以像调用方法一样调用委托完成某个功能,或返回某类结果.但是.Net毕竟是更高级的语言,委托Delegate也更高级了,委托是一种数据接口,它包含调用目标和调用方法的指针:而在.Net中定义的委托都继承自MulticastDelegate即多播委托,所谓的多播委托是指可以包含多个调用方法的委托.一. 先来看下委托的定义:如下C#代码定义委托public delegate void DoSomething(int times);委托的定

Java开发中的23种设计模式详解(转)

Java开发中的23种设计模式详解(转) 设计模式(Design Patterns)                                   --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合

Android Handler多线程详解_Android

Android--多线程之Handler 前言 Android的消息传递机制是另外一种形式的"事件处理",这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的UI组件,这样会导致新启动的线程无法改变UI组件的属性值.但实际开发中,很多地方需要在 工作线程中改变UI组件的属性值,比如下载网络图片.动画等等.本篇博客主要介绍Handler是如何发送与处理线程上传递来的消息,并讲解 Message的几种传递数

Android 多线程处理之多线程详解_Android

handler.post(r)其实这样并不会新起线程,只是执行的runnable里的run()方法,却没有执行start()方法,所以runnable走的还是UI线程. 1.如果像这样,是可以操作ui,但是run还是走在主线程,见打印出来的Log线程名字是main,说明是主线程. 这就是为什么可以直接在run方法里操作ui,因为它本质还是ui线程 handler.post(new Runnable(){ public void run(){ Log.e("当前线程:",Thread.c

java 线程创建多线程详解_java

Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.start(); 在上面的例子中,我们并没有为线程编写运行代码,因此调用该方法后线程就终止了. 编写线程运行时执行的代码有两种方式:一种是创建 Thread 子类的一个实例并重写 run 方法,第二种是创建类的时候实现 Run

Java Thread多线程详解及用法解析_java

最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); public Thread(Runnab