多线程

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

一、简单使用

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

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

比以前使用Thread方便多了吧。

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

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

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

结论1:如果不需要使用IsBackground,那么尽情的使用Task吧。经测试,Task是后台线程,也就是Isbackground=true;

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

也就是两个线程,有序的执行,这里使用ContinueWith(),

t执行完毕后再执行一个task方法,不多说了代码如下:

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

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

         /// <summary>
/// Task 执行完毕后调用另一个Task(链式写法)
/// </summary>
private void Demo4()
{
Random r = new Random(DateTime.Now.Second);
Task<int> t = new Task<int>(() =>
{
int i = ;
for (int v = ; v < ; v++)
i += r.Next();
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。

        /// <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 = ;
Random r = new Random(DateTime.Now.Second);
for (int v = ; v < ; v++)
i += r.Next();
return i;
}, TaskCreationOptions.AttachedToParent);
Task<int> t2 = new Task<int>(() =>
{
int i = ;
Random r = new Random(DateTime.Now.Second);
for (int v = ; v < ; v++)
i += r.Next();
return i;
}, TaskCreationOptions.AttachedToParent);
Task<int> t3 = new Task<int>(() =>
{
int i = ;
Random r = new Random(DateTime.Now.Second);
for (int v = ; v < ; v++)
i += r.Next();
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的中断

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

        /// <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 ctoken = cts.Token;
Task t1 = new Task(() =>
{
for (int v = ; v < ; v++)
{
if (ctoken.IsCancellationRequested)
{
//第一种写法
//这个会抛出异常
ctoken.ThrowIfCancellationRequested();
//另一种写法
//这个不会返回异常,但是获取不到是否是中断还是执行完毕。
//return;
}
Thread.Sleep();
Console.WriteLine(v);
}
}, ctoken);
t1.Start();
Thread.Sleep();
cts.Cancel();
try
{
t1.Wait();
}
catch
{
if (t1.IsCanceled)
Console.WriteLine("cancel");
}
Console.ReadLine();
cts.Dispose();
}

结论4:中断很复杂,但是对一般逻辑来说,是没有很大必要的。

五、其他

这里介绍下另一种写法Task.Factory,以及ContinueWhenAny和ContinueWhenAll两个方法。

Task.Factory是静态工厂类,用于对Task提供一些麻烦的支持,这里主要介绍ContinueWhenAny和ContinueWhenAll。

ContinueWhenAll所指定的函式会在传入的所有Tasks结束时执行,只会执行一次。

ContinueWhenAny所指定的函式会在传入的Tasks中有任何一个结束时执行,且与ContinueWhenAll相同,只会执行一次。

好了,还是看代码:

        /// <summary>
/// Task.Factory
/// ContinueWhenAny和ContinueWhenAll
/// ContinueWhenAll所指定的函式会在传入的所有Tasks结束时执行,只会执行一次。
/// ContinueWhenAny所指定的函式会在传入的Tasks中有任何一个结束时执行,且与ContinueWhenAll相同,只会执行一次。
/// </summary>
private void Demo7()
{
Task<int> t1 = Task.Factory.StartNew<int>(() =>
{
int total = ;
for (int i = ; i < ; i++)
total += i;
Thread.Sleep();
return total;
});
Task<int> t2 = Task.Factory.StartNew<int>(() =>
{
int total = ;
for (int i = ; i < ; i++)
total += i;
Thread.Sleep();
return total;
});
Task tfinal = Task.Factory.ContinueWhenAny<int>(
new Task<int>[] { t1, t2 }, (Task<int> task) =>
{
if (task.Status == TaskStatus.RanToCompletion)
{
Console.WriteLine(task.Result);
}
});
Console.ReadLine();
}

结论5:ContinueWhenAny和ContinueWhenAll对特定条件执行,还是有些用处的。

原文地址:http://www.cnblogs.com/sorex/archive/2010/09/18/1830130.html

【转】【C#】【Thread】【Task】多线程的更多相关文章

  1. Task多线程

    Task多线程  1.首先是我们线程之间的启动. 1.这样 Task task = new Task(()=> { // System.Threading.Thread.Sleep(); Con ...

  2. iOS多线程之1.从Thread看多线程的生命周期

      Thread 是多线程中最容易理解,但是使用起来又是最麻烦的一种多线程方法.为什么说容易理解呢?一个NSThread的对象就是一条线程.使用起来麻烦是因为,需要我们自己管理线程的生命周期:创建线程 ...

  3. C++使用thread类多线程编程

    转自:C++使用thread类多线程编程 C++11中引入了一个用于多线程操作的thread类,下面进行简单演示如何使用,以及如果进行多线程同步. thread简单示例 #include <io ...

  4. C# Task多线程

    来自Eleven老师示例 private void btnTask_Click(object sender, EventArgs e) { Console.WriteLine(); Console.W ...

  5. Runnable,Thread实现多线程以及Runnable的同步资源共享

    (一) 实现多线程有两种方式 (1) 继承Thread类,重写run()方法,如以下例子 class MyThread extends Thread{ public void run(){ // } ...

  6. C#实现异步编程的两个简单机制(异步委托&定时器)及Thread实现多线程

    创建线程的常用方法:异步委托.定时器.Thread类 理解程序.进程.线程三者之间的区别:简而言之,一个程序至少有一个进程,一个进程至少有一个线程进程就是在内存中运行的程序(即运行着的程序):一个进程 ...

  7. Thread Runnable 多线程

    1. 实现多线程的两种方法         a) 让这个类继承java.lang.Thread,然后重写run方法         b) 让这个类实现 java.lang.Runnable接口,实现r ...

  8. 【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17161237 Java中实现多线程有两种方法:继承Thread类.实现Runnable接口 ...

  9. C++ thread类多线程编程

    https://blog.csdn.net/dcrmg/article/details/53912941 多线程操作的thread类,简单多线程示例: #include <iostream> ...

  10. 【Java并发编程】:Runnable和Thread实现多线程的区别

    Java中实现多线程有两种方法:继承Thread类.实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下 ...

随机推荐

  1. 用doxygen+graphviz自动化生成代码文档(附详细教程)

    一.引子 用这两个工具可以自动的遍历代码,并且产生代码文档,我们先来看看效果,然后放出这两个工具的下载地址. 二.工具的下载地址 doxygen:http://www.stack.nl/~dimitr ...

  2. Swift开发第四篇——柯里化

    本篇分为两部分: 一.柯里化的基本使用 二.柯里化的使用场景 一.柯里化的基本使用 柯里化(Currying):也就是把接受多个参数的方法变换成接受第一个参数的方法,并且返回接受余下的参数并且返回结果 ...

  3. SqlServer int型转varchar型 出现*号

    今天调一个bug,错误提示执行语句 * 附近有语法错误,看了存储过程半天没啥反应,我就更本没有* .打印了一下语句发现 where Mor_Id=* 仔细一看set @sqlupdate+=' whe ...

  4. 如何在sublime text 3 上安装插件package control

    今天由于帮同事搞web方面的东西,于是又重新安装了sublime text 这款神器.发现官方网站都更新到sublime text3了,于是下载装了下,突然发现少了很重要的一个功能,竟然没有packa ...

  5. IE无法正常打开QC的解决方案

    方案一: 用兼容视图方式打开.(亲测IE10 可行) 方案二:(使用版本IE6-IE10) 1.安装过程中Jboss服务键入windows系统用户名密码域时总是提示用户名密码不正确! 解决方法:我的电 ...

  6. 对石家庄铁道大学网站首页进行UI分析

    对石家庄铁道大学网站首页进行UI界面分析首先,铁道大学的网页首页分为图文热点,学校新闻,校内公告,媒体看铁大,学术咨询等等模块.通过分析这些模块,可以看出,学校网站首页针对的使用对象有很多,包括学校领 ...

  7. android之apk反编译

    今天就来详细的讲一讲apk的反编译过程,之前自己一直没彻底搞清楚. 一.准备工作 反编译首先要准备三个工具.这三个工具都是可以百度下载的.就是下图所示的三个工具. 这三个工具是有各自作用的: (1)a ...

  8. MongoDB学习笔记——集合管理

    创建集合 使用db.createCollection(name, options) 方法创建集合 name 所创建的集合名称必选! options 可选.指定有关内存大小及索引的选项 db.creat ...

  9. 问题解决——使用GP-3120TN打印条形码标签

    终于大致的尝试出了参数和编程手册里指令的使用. 在这里,感谢佳博中一个叫做"Gprinter 陶玮"的工程师所提供的技术支持.非常感谢,如果没有你,在写这篇文章之前我可能换别的打印 ...

  10. 闭包Closures

    所谓闭包,可以理解为一个可以用于函数,参数,返回值处的代码块 import Foundation func isGood(a:Int,b:Int)->Bool{ return a>b; } ...