前面两篇回顾线程和线程池的使用方法,微软在.NET4.5推出了新的线程模型-Task。本篇将简单的介绍Task的使用方法。

Task与线程

  Task与线程或者说线程池关系紧密,可以说是基于线程池实现的,虽说任务最终还是要抛给线程去执行,但是Task仍然会比线程、线程池的开销要小,并且提供了可靠的API来控制线任务执行。

  使用Task来执行的任务最终会交给线程池来执行,若该任务需要长时间执行,可以将其标记为LongRunning,这是便会单独去请求创建线程来执行该任务。

Task

 创建

  Task的创建也存在两种方式,使用new或者使用静态工厂方式来创建:

        static void Main(string[] args)
{ Task t = new Task(Menthod1);
t.Start(); Task.Factory.StartNew(Menthod2); Console.WriteLine("主线程的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("--------------------");
Console.ReadLine();
} static void Menthod1()
{
Thread.Sleep();
Console.WriteLine("线程1的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("--------------------");
}
static void Menthod2()
{
Thread.Sleep();
Console.WriteLine("线程2的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("--------------------");
}

  上面说到使用Task执行任务最终还是需要线程池来执行,若不想让线程池来执行,可以添加LongRunning标志:

        Task t = new Task(Menthod1, TaskCreationOptions.LongRunning);
t.Start(); Task.Factory.StartNew(Menthod2, TaskCreationOptions.LongRunning);

  TaskCreationOptions还有很多枚举值,用来控制任务的更多属性。

 参数与返回值

  使用Task也可以传入参数(object类型)与返回值:

        static void Main(string[] args)
{ Task.Factory.StartNew(Menthod1, );
//int result = Task.Factory.StartNew(new Func<object, int>(Menthod3), 233).Result;
Task<int> t = Task.Factory.StartNew(new Func<object, int>(Menthod3), );
int result = t.Result; Console.WriteLine("主线程的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("result:{0}", result);
Console.WriteLine("--------------------");
Console.ReadLine();
} static void Menthod1(object obj)
{
Thread.Sleep();
Console.WriteLine("线程1的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("obj:{0}", obj);
Console.WriteLine("--------------------");
}
static int Menthod3(object obj)
{
Thread.Sleep();
Console.WriteLine("线程3的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("obj:{0}", obj);
Console.WriteLine("--------------------");
return obj;
}

  这里为了获取返回值,阻塞了主线程,这里请注意一下。

 等待Task

  可以使用Task实例的Wait方法来实现等待任务结束,也可以向多线程一样,使用WaitAll和WaitAny一样来等待多个任务结束,不过操作更为简单:

        t.Wait();
Task.WaitAll(t1, t2 ...);
Task.WaitAny(t1, t2 ...);

 取消Task

  任务也是可以事先取消的,不过需要使用CancellationTokenSource:

        static void Main(string[] args)
{
Task.Factory.StartNew(Menthod1); CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
Task.Factory.StartNew(Menthod2, cancelTokenSource.Token);
cancelTokenSource.Cancel(); Console.WriteLine("主线程的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("--------------------");
Console.ReadLine();
}

  上述代码就可以将线程2给取消掉,当然,Cancel方法可以自己找个合适的地方调用。

 继续Task

  在Task中,可以实现在一个任务结束后开启另一个新的任务:

        static void Main(string[] args)
{
Task t = Task.Factory.StartNew(Menthod1);
t.ContinueWith(new Action<Task>(Menthod4)); Console.WriteLine("主线程的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("任务t的ID:{0}", t.Id);
Console.WriteLine("--------------------");
Console.ReadLine();
} static void Menthod1()
{
Thread.Sleep();
Console.WriteLine("线程1的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("--------------------");
}
static void Menthod4(Task t)
{
Console.WriteLine("线程4的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("任务t的ID:{0}", t.Id);
Console.WriteLine("--------------------");
}

  这里因为使用了委托,也可以使用lambda表达式,更简单一些调用:

        Task t = Task.Factory.StartNew(Menthod1);
t.ContinueWith(task =>
{
Console.WriteLine("线程4的ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("任务t的ID:{0}", task.Id);
Console.WriteLine("--------------------");
});

总结

  使用传统线程方式来进行多线程编程的时候,对线程的控制总是不到位,产生一些奇奇怪怪的问题;或是代码写得很杂乱;或是开发人员乱用线程,比方说无限制的创建线程、将线程池线程占满,等等。

  Task的出现,实现对传统线程操作的封装,提供可靠高效的API来控制线程,极大的方便多线程编程,所以可以用到Task的地方尽量使用Task;当然,这里仍会产生线程安全的问题,同样需要进行线程同步,与上一篇处理方式类似。

  Task的内容还有很多,更深层的运行原理、封装还等着我们去了解,现在只把我用到的东西分享出来,希望能帮助到需要的人。

  线程的学习就先告一段落了,敬请期待新的内容吧。

菜鸟之旅——学习线程(Task)的更多相关文章

  1. [C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序

    用菜鸟的思维学习算法 -- 马桶排序.冒泡排序和快速排序 [博主]反骨仔 [来源]http://www.cnblogs.com/liqingwen/p/4994261.html  目录 马桶排序(令人 ...

  2. C#多线程之旅(3)——线程池

    v博客前言 先交代下背景,写<C#多线程之旅>这个系列文章主要是因为以下几个原因:1.多线程在C/S和B/S架构中用得是非常多的;2.而且多线程的使用是非常复杂的,如果没有用好,容易造成很 ...

  3. 上四条只是我目前总结菜鸟们在学习FPGA时所最容易跑偏的地

    长期以来很多新入群的菜鸟们总 是在重复的问一些非常简单但是又让新手困惑不解的问题.作为管理员经常要给这些菜鸟们普及基础知识,但是非常不幸的是很多菜鸟怀着一种浮躁的心态来学习 FPGA,总是急于求成. ...

  4. Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  5. C#中假设正确使用线程Task类和Thread类

    C#中使用线程Task类和Thread类小结 刚接触C#3个月左右.原先一直使用C++开发.由于公司的须要,所地採用C#开发.主要是控制设备的实时性操作,此为背景. 对于C#中的Task和Thread ...

  6. 菜鸟教程之学习Shell script笔记(下)

    菜鸟教程Shell script学习笔记(下) 以下内容是学习菜鸟教程之shell教程,所整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-sh ...

  7. 菜鸟教程之学习Shell script笔记(上)

    菜鸟教程之学习Shell script笔记 以下内容是,学习菜鸟shell教程整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-shell.ht ...

  8. Hadoop源码学习笔记(3) ——初览DataNode及学习线程

    Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...

  9. Python学习---线程/协程/进程学习 1220【all】

    Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...

随机推荐

  1. 异步处理,Event Souring,事务补偿,实现最终一致性和服务的弹性和批处理

    这段时间一直学习极客时间皓哥的分布式架构,关于异步处理有一些感想用sketch做了一个图,展示上直观一些,和大家交流下

  2. DDD「领域驱动设计」分层架构初探

    前言 基于 DDD 传统分层架构实现. 项目 github地址:https://github.com/WuMortal/DDDSample 这个分层架构是工作中项目正在使用的分层架构,使用了一段时间发 ...

  3. PHP全栈学习笔记12

    php简介,php历史,php后端工程师职业前景,php技术方向,php后端工程师职业体系介绍. php是世界上使用最广泛的web开发语言,是超文本预处理器,是一种通用的开源脚本语言,语法吸收了c语言 ...

  4. 02 JVM 从入门到实战 | 什么样的对象需要被 GC

    引言 上一篇文章 JVM 基本介绍 我们了解了一些基本的 JVM 知识,本篇开始逐步学习垃圾回收,我们都知道既然叫垃圾回收,那回收的就应该是垃圾,可是我们怎么知道哪些对象是垃圾呢? 哪些对象需要被回收 ...

  5. MySQL - 扩展性 3 负载均衡:眼花缭乱迷人眼

    负载均衡的基本思路很简单: 在一个服务器集群中尽可能地的平均负载量. 基于这个思路,我们通常的做法是在服务器前端设置一个负载均衡器.负载均衡器的作用是将请求的连接路由到最空闲的可用服务器上.如图 1, ...

  6. Vue.js-08:第八章 - 组件的基础知识

    一.前言 在之前的学习中,我们对于 Vue 的一些基础语法进行了简单的了解,通过之前的代码可以清晰的看出,我们在使用 Vue 的整个过程,最终都是在对 Vue 实例进行的一系列操作. 这里就会引出一个 ...

  7. 《HelloGitHub》第 34 期

    公告 新年快乐!大家的年终奖都发了啥? <HelloGitHub>第 34 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源 ...

  8. Eclipse连接Hadoop集群及WordCount实践

    声明:作者原创,转载注明出处. 作者:帅气陈吃苹果 一.环境准备 1.JDK安装与配置 2.Eclipse下载 下载解压即可,下载地址:https://pan.baidu.com/s/1i51UsVN ...

  9. 【野草】SQL Server之索引解析(一)

    1.写在前面 微软专门给出SQL Server设计思路及实现路线,从7大体系结构阐述是如何实现,通过了解这些,我们就可以总结出数据库设计原则.编程中sql写法及注意事项,从而优化我们的系统性能,本系列 ...

  10. Deepin linux Compass.app安装

    compass.app是集成了sass的工具,安装完Compass就能够使用sass. 首先,上官网 可以看到官网上推荐的两种sass使用方式,application&command line ...