前一篇中,了解了Task的基本用法

如果一个方法返回Task,Task<T>,如何获取Task的返回值,获取值的过程会阻塞线程吗?

  1.         static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             var result = DoWorkAsync().Result;
  6.  
  7.             Console.WriteLine(result);
  8.  
  9.             Console.WriteLine("我会什么时候显示");
  10.  
  11.             Console.ReadKey();
  12.  
  13.         }
  14.  
  15.         static Task<string> DoWorkAsync()
  16.  
  17.         {
  18.  
  19.             return Task<string>.Factory.StartNew(() =>
  20.  
  21.             {
  22.  
  23.                 Thread.Sleep(3000);
  24.  
  25.                 return "hello";
  26.  
  27.             });
  28.  
  29.         }
  30.  

可见,Task的Result属性可以获取返回值,而且,获取返回值的过程线程是被阻塞的。

是否可以不阻塞线程,又能拿到某个线程的返回值呢?ContinueWith方法在某个线程结束之后进行,但同时不会阻塞线程。

  1.         static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             DoWorkAsync().ContinueWith((pre) =>
  6.  
  7.             {
  8.  
  9.                 Console.WriteLine(pre.Result);
  10.  
  11.             });
  12.  
  13.             Console.WriteLine("我会什么时候显示");
  14.  
  15.             Console.ReadKey();
  16.  
  17.         }

但ContinueWith总会在某个线程结束之后进行,是否可以对ContinueWith的过程控制一下呢?

  1.         static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             DoWorkAsync().ContinueWith((pre) =>
  6.  
  7.             {
  8.  
  9.                 Console.WriteLine(pre.Result);
  10.  
  11.             }, TaskContinuationOptions.NotOnFaulted);
  12.  
  13.             DoWorkAsync().ContinueWith((pre) =>
  14.  
  15.             {
  16.  
  17.                 Console.WriteLine(pre.Exception);
  18.  
  19.             },TaskContinuationOptions.OnlyOnFaulted);
  20.  
  21.             Console.WriteLine("我会什么时候显示");
  22.  
  23.             Console.ReadKey();
  24.  
  25.         }
  26.  

以上,当没有错误的时候就把返回值显示出来,有错误就把错误信息显示出来。

还可以通过Task的实例方法IsCompleted来判断一个线程是否完成。

  1.         static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             var doWorkTask = DoWorkAsync();
  6.  
  7.             if (doWorkTask.IsCompleted)
  8.  
  9.             {
  10.  
  11.                 Console.WriteLine(doWorkTask.Result);
  12.  
  13.             }
  14.  
  15.             else
  16.  
  17.             {
  18.  
  19.                 doWorkTask.ContinueWith((pre) =>
  20.  
  21.                 {
  22.  
  23.                     Console.WriteLine(pre.Result);
  24.  
  25.                 }, TaskContinuationOptions.NotOnFaulted);
  26.  
  27.                 doWorkTask.ContinueWith((pre) =>
  28.  
  29.                 {
  30.  
  31.                     Console.WriteLine(pre.Exception);
  32.  
  33.                 }, TaskContinuationOptions.OnlyOnFaulted);
  34.  
  35.             }
  36.  
  37.             Console.WriteLine("我会什么时候显示");
  38.  
  39.             Console.ReadKey();
  40.  
  41.         }
  42.  

Task的Status属性,以及结合TaskStatus枚举,可以判断Task的状态。

  1.       static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             var httpClient = new HttpClient();
  6.  
  7.             Task<string> baiduTask = httpClient.GetStringAsync("http://www.baidu.com");
  8.  
  9.             var httpClient2 = new HttpClient();
  10.  
  11.             Task<string> sinaTask = httpClient2.GetStringAsync("http://www.sina.com.cn");
  12.  
  13.             //等上面2个任务完成时这里再开始
  14.  
  15.             Task<string[]> task = Task.WhenAll(baiduTask, sinaTask);
  16.  
  17.             task.ContinueWith(stringArray =>
  18.  
  19.             {
  20.  
  21.                 //如果任务完成
  22.  
  23.                 if (task.Status == TaskStatus.RanToCompletion)
  24.  
  25.                 {
  26.  
  27.                     for (int i = 0; i < stringArray.Result.Length;i++)
  28.  
  29.                     {
  30.  
  31.                         Console.WriteLine(stringArray.Result[i].Substring(0,100));
  32.  
  33.                     }
  34.  
  35.                 }
  36.  
  37.                 else if (task.Status == TaskStatus.Canceled) //如果被取消
  38.  
  39.                 {
  40.  
  41.                     Console.WriteLine("{0}这个任务被取消了",task.Id);
  42.  
  43.                 }
  44.  
  45.                 else //发生错误
  46.  
  47.                 {
  48.  
  49.                     Console.WriteLine("发生错误了~~");
  50.  
  51.                     foreach (var item in task.Exception.InnerExceptions)
  52.  
  53.                     {
  54.  
  55.                         Console.WriteLine(item.Message);
  56.  
  57.                     }
  58.  
  59.                 }
  60.  
  61.             });
  62.  
  63.             Console.ReadKey();
  64.  
  65.         }
  66.  

如果要控制Task的生命周期,可以考虑使用TaskCompletionSource<T>。

  1.        static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             AsyncFactory.GetIntAsync().ContinueWith((prev) =>
  6.  
  7.             {
  8.  
  9.                 if (prev.Status == TaskStatus.RanToCompletion)
  10.  
  11.                 {
  12.  
  13.                     Console.WriteLine(prev.Result);
  14.  
  15.                 }
  16.  
  17.                 else if (prev.Status == TaskStatus.Canceled)
  18.  
  19.                 {
  20.  
  21.                     Console.WriteLine("任务被取消");
  22.  
  23.                 }
  24.  
  25.                 else
  26.  
  27.                 {
  28.  
  29.                     Console.WriteLine("发生错误哦");
  30.  
  31.                     Console.WriteLine(prev.Exception);
  32.  
  33.                 }
  34.  
  35.             });
  36.  
  37.             Console.ReadKey();
  38.  
  39.         }
  40.  
  41.     }
  42.  
  43.     public static class AsyncFactory
  44.  
  45.     {
  46.  
  47.         public static Task<int> GetIntAsync()
  48.  
  49.         {
  50.  
  51.             var tsc = new TaskCompletionSource<int>();
  52.  
  53.             var timer = new System.Timers.Timer(2000);
  54.  
  55.             timer.AutoReset = false;
  56.  
  57.             timer.Elapsed += (s, e) =>
  58.  
  59.             {
  60.  
  61.                 tsc.SetResult(10);
  62.  
  63.                 timer.Dispose();
  64.  
  65.             };
  66.  
  67.             timer.Start();
  68.  
  69.             return tsc.Task;
  70.  
  71.         }
  72.  
  73.     }
  74.  

以上,通过TaskCompletionSource<T>的SetResult给线程设置返回值,通过TaskCompletionSource<T>的.Task有获取了线程。

另外,从.NET 4.5开始,Task的静态方法FromResult,接收T类型,返回Task<T>。

  1.         static void Main(string[] args)
  2.  
  3.         {
  4.  
  5.             var intTask = GetIntAsync();
  6.  
  7.             if (intTask.Status == TaskStatus.RanToCompletion)
  8.  
  9.             {
  10.  
  11.                 Console.WriteLine(intTask.Result);
  12.  
  13.             }
  14.  
  15.             else if (intTask.Status == TaskStatus.Canceled)
  16.  
  17.             {
  18.  
  19.                 Console.WriteLine("任务被取消");
  20.  
  21.             }
  22.  
  23.             else
  24.  
  25.             {
  26.  
  27.                 Console.WriteLine("发生错误哦");
  28.  
  29.                 Console.WriteLine(intTask.Exception);
  30.  
  31.             }
  32.  
  33.             Console.ReadKey();
  34.  
  35.         }
  36.  
  37.         static Task<int> GetIntAsync()
  38.  
  39.         {
  40.  
  41.             return Task.FromResult(10);
  42.  
  43.         }
  44.  

Task Parallel Library02,更进一步的更多相关文章

  1. C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)

    学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...

  2. Using the Task Parallel Library (TPL) for Events

    Using the Task Parallel Library (TPL) for Events The parallel tasks library was introduced with the ...

  3. TPL(Task Parallel Library)多线程、并发功能

    The Task Parallel Library (TPL) is a set of public types and APIs in the System.Threading and System ...

  4. Task Parallel Library01,基本用法

    我们知道,每个应用程序就是一个进程,一个进程有多个线程.Task Parallel Library为我们的异步编程.多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也 ...

  5. Winform Global exception and task parallel library exception;

    static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...

  6. C#~异步编程再续~大叔所理解的并行编程(Task&Parallel)

    返回目录 并行这个概念出自.net4.5,它被封装在System.Threading.Tasks命名空间里,主要提供一些线程,异步的方法,或者说它是对之前Thread进行的二次封装,为的是让开发人员更 ...

  7. Task/Parallel实现异步多线程

    代码: #region Task 异步多线程,Task是基于ThreadPool实现的 { //TestClass testClass = new TestClass(); //Action<o ...

  8. 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource

    1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...

  9. FunDA(15)- 示范:任务并行运算 - user task parallel execution

    FunDA的并行运算施用就是对用户自定义函数的并行运算.原理上就是把一个输入流截分成多个输入流并行地输入到一个自定义函数的多个运行实例.这些函数运行实例同时在各自不同的线程里同步运算直至耗尽所有输入. ...

随机推荐

  1. java 异常使用指南

    应该在以下情况使用异常: 1.)在恰当的级别处理问题.(在知道如何处理的情况下才捕获异常) 2.)解决问题并且重新调用异常的方法 3.)进行少许的修补,然后绕过异常发生的地方继续执行 4.)用别的数据 ...

  2. Java @Override 注解

    @Override注解,不是关键字,但可以当关键字使用,可以选择添加这个注解,在你不留心重载而并非复写了该方法时,编译器就会产生一条错误:The method doh(Milhouse) of typ ...

  3. Laravel 的 JSON API 接口自动化测试

    Laravel 自带了两种测试类型 Feature Test: 功能测试.针对类似接口这种流程性的测试. Unit Test: 单元测试.针对单个函数这种输入输出结果的测试. 新建一个 Feature ...

  4. python标准模块(下)

    Python 系统标准模块(shutil.logging.shelve.configparser.subprocess.xml.yaml.自定义模块) 目录: shutil logging模块 she ...

  5. 002_JavaSE笔记:单例模式

    一.应用杨景 在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printer ...

  6. <转> 解决异常:IllegalStateException: Fragment <ThisFragment> is not currently in the FragmentManager

    上午敲代码时出现这个问题,简单记录一下解决办法,有时间详细描述一下深层原因. 问题出现在这: @Override public void onSaveInstanceState(Bundle outS ...

  7. IIS开多个HTTPS站点

    默认情况一个服务器的IIS只能绑定一个HTTPS也就是443端口 要实现多个站点对应HTTPS只能更改IIS配置 地址:C:\Windows\system32\inetsrv\config\appli ...

  8. PHP实现数据分页显示

    分页在后台管理中是经常使用的功能,分页显示方便大量数据的管理. 实例代码如下: <!DOCTYPE html> <html> <head> <meta cha ...

  9. CMU-15445 LAB1:Extendible Hash Table, LRU, BUFFER POOL MANAGER

    概述 最近又开了一个新坑,CMU的15445,这是一门介绍数据库的课程.我follow的是2018年的课程,因为2018年官方停止了对外开放实验源码,所以我用的2017年的实验,但是问题不大,内容基本 ...

  10. 利用transform的bug使fixed相对于父级定位

    首先,大家都清楚,元素使用fixed之后,若不设置top与left则会相对于最近的使用定位的父元素,并位于父元素的原点位置设置top与left值时,则会相对于窗口定位.但无论如何,此时仍相对于窗口定位 ...