前一篇中,了解了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. python3之SQLAlchemy

    1.SQLAlchemy介绍 SQLAlchemy是Python SQL工具包和对象关系映射器,为应用程序开发人员提供了SQL的全部功能和灵活性. 它提供了一整套众所周知的企业级持久性模式,专为高效和 ...

  2. MYSQL问题解决

    1. MySQL错误日志里出现: 140331 10:08:18 [ERROR] Error reading master configuration 140331 10:08:18 [ERROR] ...

  3. 数据库SQL中case when函数的用法

    Case具有两种格式,简单Case函数和Case搜索函数.这两种方式,可以实现相同的功能.简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式. 简单Cas ...

  4. PHP+mysql系统报错:PHP message: PHP Warning: Unknown: Failed to write session data (files)

    PHP+mysql系统报错:PHP message: PHP Warning:  Unknown: Failed to write session data (files) 故障现象,后台页面点击没有 ...

  5. 使用JS实现俄罗斯方块游戏

    简单的JS俄罗斯方块游戏源码 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <meta charset=&q ...

  6. 使用VSCode创建.NET Core 项目,添加类库间引用

    注:网络上搜索到的关于VsCode创建调试.Net Core 项目的文章都比较老旧,不能完全参考使用,根据网络文章.微软官方文档的指导下,学习并整理此文档,但也大体和文档学习路线相似,主要为记录学习过 ...

  7. django为url写测试用例

    这个和为orm写测试用例类似. 但为了区分文件,还是建议在app目录下,用tests_orm.py,tests_url.py这类单独文件加以区分. urls.py如果如这样. from django. ...

  8. Mysql中count(*)和limit同时使用的问题

    1.带有count的sql语句只会返回一条记录 , 结果如下图: 2.带有limit的sql语句是最后执行的 , 以上sql语句将返回空行,因为count(*)只会使sql语句产生一条结果记录,所以后 ...

  9. 【AtCoder】AGC020

    A - Move and Win 题解 看两个人相遇的时候谁先手即可,相遇之后第一个移动的人必输 代码 #include <bits/stdc++.h> #define fi first ...

  10. 【BZOJ】4561: [JLoi2016]圆的异或并

    题解 我们把圆拆成两个圆弧,按照圆弧的左右端点排序来增加和删除 那么我们把圆弧按照纵坐标排序,一定是两两不相交的 我们新加入一个圆的时候,找上圆弧的前驱,如果前驱是一个上圆弧,那么这个上圆弧所在的圆就 ...