前一篇中,了解了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. Android sdk安装目录中没有platform-tools目录问题详解

    sdk下载地址 http://tools.android-studio.org/index.php/sdk 安装步骤很简单,百度即可. 下面详细说一下,在安装中遇到android sdk下没有plat ...

  2. JavaScript——创建对象

    <script type="text/javascript"> //声明变量的首字母是小写 //1.对象字面量 /*var person = { name:" ...

  3. 初始ASP.NET数据控件【续 DataList】

    DataList控件  DataList控件也是一个常用的数据绑定控件,相对于GridView控件虽然没它那么强大的功能,但是灵活性却很强势.因为其本身就是一个富有弹性的控件.DataList控件可以 ...

  4. 压缩跟踪Compressive Tracking(转)

    这位博主总结的实在太好了,从原理到论文到代码,连论文都不用看:论文:http://blog.csdn.net/zouxy09/article/details/8118360 代码部分:http://b ...

  5. 当Python与数模相遇

    数模有一个题目要处理杭州自行车在每个站点可用数量和已经借出数量,这数据在www.hzbus.cn上可以获取,它是10分钟更新一次的.这些数据手动获取,需要不停的刷页面,从6:00am到9:00pm,显 ...

  6. iOS企业包安装注意事项详解(解决提示iPhone未受信任的问题)

    请在Safari浏览器上打开该页面才能正常安装. 如果您是微信中查看该页面,请点击右上角,在弹出的菜单中选择“在Safari中打开” 对于iOS版本为7.X和8.X的用户,直接点击安装即可(此处为it ...

  7. Java web项目使用webSocket

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

  8. DRF分阶段序列化细化实例

    DRF是分两阶段进行的. 如果是API接收数据,则是先进行Parser,将外界接收的bytes数据分析成python数据类型,其间涉及encoding操作,再进行序列化,将python数据类型保存进数 ...

  9. tidb 升级步骤

    1.检查ansible版本,正常情况下,2.1 rc3需要兼容ansible 2.5以上的版本 $ ansible --version 2.检查python两个模块jinja2需要升级到2.9.6或以 ...

  10. Pomelo分布式游戏服务器框架

    Pomelo介绍&入门 目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json ...