.NET异步编程之------Task

  一.FrameWork 4.0之前的线程世界    

  在.NET FrameWork 4.0之前,如果我们使用线程。一般有以下几种方式:

  1.使用System.Threading.Thread 类,调用实例方法Start()开启一个新线程,调用Abort()方法来提前终止线程。

  2.使用System.Threading.ThreadPool类,调用静态方法QueueUserWorkItem(),将方法放入线程池队列,线程池来控制调用。

  3.使用BeginInvoke,EndInvoke,BeginRead,EnRead,BeginWrite,EndWrite等一系列的异步方法。

  4.使用System.ComponentModel.BackgroundWorker控件,调用实例方法RunWorkerAsync(),开启一个新线程。 

  二.创建一个新线程时会产出哪些开销

  1.线程内核对象,包含一组对线程进行描述的属性。

   2.线程环境块,包含线程异常处理的链首,线程进入的每个try{}块会在链首插入一个节点,从try{}块推出时,会在链首删除该节点。

   3.用户模式栈,用来存储传给方法的局部变量和实参,它还包含一个地址,指出当前方法返回知,该从什么地方继续执行。

   4.内核模式栈,应用程序代码向操作系统中的一个内核模式的函数传递实参时,会使用内核模式栈。

   5.DLL线程附加和线程分离通知,线程开启或者终止时,会调用进程中加载的所有DLL的DLLMain方法。

  三.线程池

   由于创建一个新的线程是一个昂贵的操作,所以有了线程池来维护了一个线程队列,例如常见的数据库连接池,IIS连接池等。线程池在FrameWork 4.0之前,我们可以使用ThreadPool.QueueUserWorkItem()将一个符合WaitHandle委托类型的方法加入到线程池队列中。

代码如下:

 1  static void Main(string[] args)2         {3             Console.WriteLine("Main");4             ThreadPool.QueueUserWorkItem((o) =>5             {6                 Console.WriteLine(DateTime.Now);7             });8             Thread.Sleep(1000);9             Console.WriteLine("Main Next...");
10             Console.Read();
11         }

为了验证线程池内的方法确实是异步的,我们在Main方法中让主线程停止1秒。测试结果确实是线程池内的方法和Main方法是异步执行的。

  四.取消操作

   FrameWork提供了一个取消操作的模式,这就意味着我们可以取消正在执行的操作,对于耗时的操作来说,是非常好的用户体验。为了取消一个操作,要创建一个System.Threading.CancellationTokenSource类的实例。(MSDN入口http://msdn.microsoft.com/zh-cn/library/vstudio/system.threading.cancellationtokensource.aspx

)。这个对象包含了管理和取消的所有状态,Token属性可以获取CancellationToken的实例,可以根据IsCancellationRequested属性来判断是否需要取消操作。同时,可以通Register方法注册一个在取消时调用的委托。

代码如下:

 1  static void Main(string[] args)2         {3             CancellationTokenSource cts = new CancellationTokenSource();4             cts.Token.Register(() => Console.WriteLine("Register"));5             Console.WriteLine("Main");6             ThreadPool.QueueUserWorkItem((o) =>7             {8                 CancellationToken ct = (CancellationToken)o;9
10                 for (int i = 0; i < 100; i++)
11                 {
12                     //是否需要取消操作
13                     if (ct.IsCancellationRequested)
14                     {
15                         break;
16                     }
17                     Console.WriteLine(DateTime.Now);
18                     Thread.Sleep(100);
19                 }
20
21
22             }, cts.Token);
23             Thread.Sleep(1000);
24             //取消
25             cts.Cancel();
26             Console.WriteLine("Main Next...");
27             Console.Read();
28         }

可以看到在Main方法中创建了CancellationTokenSource的实例,同时注册了一个在取消时调用的委托,并且把这个实例传给了线程池方法。在线程池方法的循环内判断是否需要取消任务,最后在Main方法内调用cts.Cancel()取消了操作。

  五.Task(任务)

  1.创建任务

  调用ThreadPool.QueueUserWorkItem()方法来处理异步的操作是非常简单的。但是这个是有很多限制的。比如,我们不知道线程池什么时候开始执行方法,什么时候方法执行结束,而且也没有方法的返回值。所以在FrameWork 4.0里,引入了Task的概念。我们可以在 System.Threading.Tasks命名空间下找到它们(MSDN入口http://msdn.microsoft.com/zh-cn/library/vstudio/system.threading.tasks.task.aspx),可以用Task做同样的异步操作。

代码如下:

static void Main(string[] args)
        {
            Console.WriteLine("Main");
            Task<int> task = new Task<int>(() =>
            {
                int sum = 0;
                for (int i = 0; i <= 1000; i++)
                {
                    Thread.Sleep(10);
                    sum += i;
                }
                return sum;
            });
            task.Start();
            Console.WriteLine(task.Result);//获取任务的执行结果
            Console.Read();
        }

  要注意的是调用task.Result获取返回值,或者是task.Wait()等待任务执行完成,主线程将会被阻塞。要等到Task执行完成才会继续执行。同时,如果Task内部抛出了一个未处理的异常,这个异常会在调用Result或者Wait()是时候会抛出System.AggregateException。

   2.一个任务完成后自动执行一个新任务

  由于调用task.Result或者task.Wait()时会阻塞,所以Task提供了一个ContinueWith()方法,有很多重载。这个方法可以在一个任务完成时,启动一个新任务,并不阻塞主线程。

代码如下:

 1  static void Main(string[] args)2         {3             Console.WriteLine("Main");4             Task<int> task = new Task<int>(() =>5             {6                 int sum = 0;7                 for (int i = 0; i <= 1000; i++)8                 {9                     Thread.Sleep(10);
10                     sum += i;
11                 }
12
13                 return sum;
14             });
15             task.Start();
16             task.ContinueWith((t) => Console.WriteLine(t.Result));//获取任务的执行结果
17             Console.WriteLine("Main Next");
18             Console.Read();
19         }

  要注意的是,执行到ContinueWith的时候,可能第一个求和的任务已经完成了。不过这不影响结果,ContinueWith方法会立即启动第二个任务。

   3.任务的状态

  Task内部有Status的只读属性,这个的属性是TaskStatus类型的枚举。在Task对象的生存期间,可以通过Status获取任务的的当前状态。这个枚举的状态的定义如下:

 1    public enum TaskStatus
 2     {
 3         Created = 0,                     //该任务已初始化,但尚未被计划
 4
 5         WaitingForActivation = 1,        //该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。
 6
 7         WaitingToRun = 2,                //该任务已被计划执行,但尚未开始执行。
 8
 9         Running = 3,                     //该任务正在运行,但尚未完成。
10
11         WaitingForChildrenToComplete = 4,//该任务已完成执行,正在隐式等待附加的子任务完成。
12
13         RanToCompletion = 5,             //已成功完成执行的任务。
14
15         Canceled = 6,                    //该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,
16                                          // 此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的CancellationToken 发出了信号。
17
18         Faulted = 7,                     // 由于未处理异常的原因而完成的任务。
19     }

  在创建一个Task对象时,状态是Created。当调用Start()方法,任务启动时,状态变成了WaitingToRun(),任务真正开始执行时,状态变成了Running,任务结束时,对应的三种不同的状态:成功、被取消、执行中出现未处理异常,分别对应:RanToCompletion、Canceled、Faulted。

SignalR介绍与Asp.net相关推荐

  1. plesk mysql nav连接_全能型空间plesk网站控制面板介绍支持ASP/ASP.NET/MSSQL/PHP/MYSQL/

    本空间环境是Windows server 2008 R2+iis7+URLWRITE+ASP.NET+ASP+PHP+MYSQL+MSSQL+GZIP,全能型空间!完美支持wordpress.Z-BL ...

  2. 微服务介绍及Asp.net Core实战项目系列之微服务介绍

    0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.微服务选型 在做微服务架构的技术选型的时候,以"无侵入"和"社区活跃"为主要的考量点, ...

  3. 介绍“Razor”— ASP.NET的一个新视图引擎

    我的团队当前正在从事的工作之一就是为ASP.NET添加一个新的视图引擎. 一直以来,ASP.NET MVC都支持 "视图引擎"的概念-采用不同语法的模板的可插拔模块.当前ASP.N ...

  4. Asp.net SignalR 应用并实现群聊功能 开源代码

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  5. asp.net core 中使用 signalR(二)

    asp.net core 使用 signalR(二) Intro 上次介绍了 asp.net core 中使用 signalR 服务端的开发,这次总结一下web前端如何接入和使用 signalR,本文 ...

  6. 发现 ASP.NET Core SignalR

    ASP.NET SignalR 是几年前推出的工具,可供 ASP.NET 开发人员使用,以向应用程序添加实时功能.只要基于 ASP.NET 的应用程序必须接收来自服务器(从监视系统到游戏)的频繁异步更 ...

  7. Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)

    前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于SignalR Core的文章了. 先介绍一下SignalR吧,如下: ASP.NET S ...

  8. asp隐藏邮箱部分字符_asp.net core 中使用 signalR(二)

    asp.net core 使用 signalR(二) Intro 上次介绍了 asp.net core 中使用 signalR 服务端的开发,这次总结一下web前端如何接入和使用 signalR,本文 ...

  9. Asp.Net 构架(HttpModule 介绍)

    Http 请求处理流程 和 Http Handler 介绍 这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了IHttpHandler接口的类进行处理 ...

最新文章

  1. Core Text 学习笔记-基础
  2. lattice diamond 3.7安装破解
  3. 录制声音并且播放录取的声音
  4. Android——监听事件总结
  5. 联想微型计算机功率,解锁全部潜力,联想这款笔记本可以将CPU功耗提升至24W
  6. mvc html绑定变量,c# – Asp.Net MVC 3使用变量对象进行自定义模型绑定
  7. 让自定义view宽高成比例显示
  8. 【题解】守望者的逃离
  9. 运维项目经验示例(参考)
  10. WIN98 当年的记忆
  11. C11中auto的使用
  12. sap ui5 中使用echarts
  13. Django模型层(2)
  14. 热搜第一!中国烟草总公司工资曝光,员工人均年收入超18万元!网友:简直是不锈钢饭碗!...
  15. filecoin lotus 转账fil流程和gas计算
  16. CANopen协议本质
  17. 程序员必读经典书籍 (转)
  18. jedispool 为redis保驾护航
  19. scrapy爬取优信二手车
  20. Java入门之基础程序设计

热门文章

  1. 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(HDU-2191)
  2. 麦森数(洛谷-P1045)
  3. 最长上升子序列(信息学奥赛一本通-T1281)
  4. 理论基础 —— 查找 —— 二分查找
  5. 烤鸡(洛谷-P2089)
  6. 不与最大数相同的数字之和(信息学奥赛一本通-T1113)
  7. 31 SD配置-主数据-信用管理-定义自动信贷控制
  8. 9 MM配置-主数据-维护物料管理的公司代码
  9. 15 FI配置-财务会计-将记账期间变式分配给公司代码
  10. Ubuntu 在终端下使用命令行打开pdf文件