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

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

        static void Main(string[] args)
        {
            var result = DoWorkAsync().Result;
            Console.WriteLine(result);
            Console.WriteLine("我会什么时候显示");
            Console.ReadKey();
        }

        static Task<string> DoWorkAsync()
        {
            return Task<string>.Factory.StartNew(() =>
            {
                Thread.Sleep(3000);
                return "hello";
            });
        }

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

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

        static void Main(string[] args)
        {
            DoWorkAsync().ContinueWith((pre) =>
            {
                Console.WriteLine(pre.Result);
            });
            Console.WriteLine("我会什么时候显示");
            Console.ReadKey();
        }

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

        static void Main(string[] args)
        {
            DoWorkAsync().ContinueWith((pre) =>
            {
                Console.WriteLine(pre.Result);
            }, TaskContinuationOptions.NotOnFaulted);

            DoWorkAsync().ContinueWith((pre) =>
            {
                Console.WriteLine(pre.Exception);
            },TaskContinuationOptions.OnlyOnFaulted);

            Console.WriteLine("我会什么时候显示");
            Console.ReadKey();
        }

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

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

        static void Main(string[] args)
        {
            var doWorkTask = DoWorkAsync();
            if (doWorkTask.IsCompleted)
            {
                Console.WriteLine(doWorkTask.Result);
            }
            else
            {
                doWorkTask.ContinueWith((pre) =>
                {
                    Console.WriteLine(pre.Result);
                }, TaskContinuationOptions.NotOnFaulted);

                doWorkTask.ContinueWith((pre) =>
                {
                    Console.WriteLine(pre.Exception);
                }, TaskContinuationOptions.OnlyOnFaulted);
            }


            Console.WriteLine("我会什么时候显示");
            Console.ReadKey();
        }

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

      static void Main(string[] args)
        {
            var httpClient = new HttpClient();
            Task<string> baiduTask = httpClient.GetStringAsync("http://www.baidu.com");

            var httpClient2 = new HttpClient();
            Task<string> sinaTask = httpClient2.GetStringAsync("http://www.sina.com.cn");

            //等上面2个任务完成时这里再开始
            Task<string[]> task = Task.WhenAll(baiduTask, sinaTask);

            task.ContinueWith(stringArray =>
            {
                //如果任务完成
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    for (int i = 0; i < stringArray.Result.Length;i++)
                    {
                        Console.WriteLine(stringArray.Result[i].Substring(0,100));
                    }
                }
                else if (task.Status == TaskStatus.Canceled) //如果被取消
                {
                    Console.WriteLine("{0}这个任务被取消了",task.Id);
                }
                else //发生错误
                {
                    Console.WriteLine("发生错误了~~");
                    foreach (var item in task.Exception.InnerExceptions)
                    {
                        Console.WriteLine(item.Message);
                    }
                }
            });

            Console.ReadKey();
        }


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

       static void Main(string[] args)
        {

            AsyncFactory.GetIntAsync().ContinueWith((prev) =>
            {
                if (prev.Status == TaskStatus.RanToCompletion)
                {
                    Console.WriteLine(prev.Result);
                }
                else if (prev.Status == TaskStatus.Canceled)
                {
                    Console.WriteLine("任务被取消");
                }
                else
                {
                    Console.WriteLine("发生错误哦");
                    Console.WriteLine(prev.Exception);
                }
            });

            Console.ReadKey();
        }

    }

    public static class AsyncFactory
    {
        public static Task<int> GetIntAsync()
        {
            var tsc = new TaskCompletionSource<int>();

            var timer = new System.Timers.Timer(2000);
            timer.AutoReset = false;
            timer.Elapsed += (s, e) =>
            {
                tsc.SetResult(10);
                timer.Dispose();
            };
            timer.Start();
            return tsc.Task;
        }
    }


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

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

        static void Main(string[] args)
        {
            var intTask = GetIntAsync();

            if (intTask.Status == TaskStatus.RanToCompletion)
            {
                Console.WriteLine(intTask.Result);
            }
            else if (intTask.Status == TaskStatus.Canceled)
            {
                Console.WriteLine("任务被取消");
            }
            else
            {
                Console.WriteLine("发生错误哦");
                Console.WriteLine(intTask.Exception);
            }

            Console.ReadKey();
        }

        static Task<int> GetIntAsync()
        {
            return Task.FromResult(10);
        }

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. 『Numpy学习指南』Matplotlib绘图

    数据生成: import numpy as np import matplotlib.pyplot as plt func = np.poly1d(np.array([,,,])) func1 = f ...

  2. [原创]jQuery Validation范例

    上班无事,学习jQuery Validation,于是手写一公共范例,并收藏以便后用 验证操作类formValidatorClass.js }); 测试页index.html         * {} ...

  3. XShell 使用方法

    XShell是一款Windows下非常优秀的远程连接Linux主机的工具,是平常使用不可缺少的工具.复制和粘贴由于在linux的Shell下,Ctrl+c是中断当前指令,这个快捷键和win系统下的复制 ...

  4. Java基础86 MySQL数据库基础知识

    本文知识点(目录): 1.MySQL数据库的概述    2.MySQL数据库的管理[对数据库的操作](查询.删除.创建数据库,以及查询和修改数据库的编码模式)    3.表的管理[对数据库 表的操作] ...

  5. PHP操作Redis常用

    一.Redis连接与认证 //连接参数:ip.端口.连接超时时间,连接成功返回true,否则返回false $ret = $redis->connect('127.0.0.1', 6379, 3 ...

  6. 浅谈HIbernate

    Hiberbate是面向对象,需要把对象和数据库进行映射.与数据库无关,操作的是对象,会根据数据源和数据库的方言生成对应的sql语句进行查询,是一个优秀的java持久层解决方案,是当今主流的对象-关系 ...

  7. 2019寒假练题计划——LibreOJ刷题计划 &《信息学奥赛一本通》提高版题目

    目录 2019.1.27 #10082. 「一本通 3.3 例 1」Word Rings 题意 思路 #10083. 「一本通 3.3 例 2」双调路径 题意 思路 #10084. 「一本通 3.3 ...

  8. Java web项目使用webSocket

    前端: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&qu ...

  9. Dynamic Rankings || 动态/静态区间第k小(主席树)

    JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...

  10. NET 异步多线程,THREAD,THREADPOOL,TASK,PARALLEL

    .NET 异步多线程,THREAD,THREADPOOL,TASK,PARALLEL,异常处理,线程取消 今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主 ...