前一篇中,了解了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. 解决“tar:Exiting with failure status due to previous errors”【转】

    问题: 当我想试着用tar命令来创建一个压缩文件时,总在执行过程中失败,并且抛出一个错误说明"tar:由于前一个错误导致于失败状态中退出"("Exiting with f ...

  2. linux开启远程访问端口

    开启3306端口的tcp访问权限 /sbin/iptables -I INPUT -p tcp -dport 3306 -j ACCEPT 保存防火墙信息 /etc/rc.d/init.d/iptab ...

  3. JVM指令详解(上)

    指令码    助记符                            说明 0x00         nop                                什么都不做 0x01  ...

  4. linux(CentOS) 下mysql自动备份

    1.创建并编辑文件 /usr/sbin/bakmysql.sh,命令: vi /usr/sbin/bakmysql.sh 内容如下: db_user="root" db_passw ...

  5. SqlServer中 CREATE PARTITION FUNCTION使用

    表分区的操作三步走: 1.创建分区函数 CREATE PARTITION FUNCTION xx1(int) 解释:在当前数据库中创建一个函数,该函数可根据指定列的值将表或索引的各行映射到分区. 语法 ...

  6. .NetCore 中扩展ExceptionLess 实现链式方法添加操作日志

    在使用ExceptionLess添加日志的时候,发现还是有一些写法上的个人觉得不爽的地方,比如添加Info日志 ExceptionlessClient.Default.CreateLog(source ...

  7. hdu 5443 (2015长春网赛G题 求区间最值)

    求区间最值,数据范围也很小,因为只会线段树,所以套了线段树模板=.= Sample Input3110011 151 2 3 4 551 21 32 43 43 531 999999 141 11 2 ...

  8. IE下css bug集合-翻译自haslayout.net

    概述IE浏览器以不支持大量的css 属性出名,同时也因其支持的css属性中存在大量bug. 本页列举了IE下的一些问题,实例样本和一些我们已知的解决方法. 尽管我已经尽力按照它们本来的性质对它们进行分 ...

  9. vue1.0到2.0

    vue1.0到2.0 vue2.0 新手教程(一)   想想自己写vue的项目也写了一年了,从vue1.0到2.0,走过不少路,填过不少坑, 下面记录一下新手从0到1的过程,本文“应该”会持续更新 首 ...

  10. CUDA安装出现图形驱动程序安装失败

    win7安装cuda9时出现图形驱动程序安装失败,解决办法是右键计算机>管理>服务和应用程序>服务>找到“Windows Installer”,右键选择“启动” 参考自http ...