zoukankan      html  css  js  c++  java
  • Task Parallel Library02,更进一步

    前一篇中,了解了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";
    
                });
    
            }
    

    1

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

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

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

    2

    但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);
    
            }
    
  • 相关阅读:
    打开安装 好的Microsoft Dynamics CRM 4.0 报错误为 Caller does not have enough privilege to set CallerOriginToken to the specified value 的解决办法
    基于 Windows Server 2008 的计算机对 Microsoft Dynamics CRM 4.0 的支持
    Microsoft Dynamics CRM 4.0 如何添加自定义按钮
    Microsoft Dynamics CRM 4.0 Plugin 取值,赋值,查询
    C# 中的 enum(枚举) 类型使用例子
    vue事件的绑定
    表单验证2
    node中模块
    node模块的引入
    node中的读文件
  • 原文地址:https://www.cnblogs.com/darrenji/p/4438706.html
Copyright © 2011-2022 走看看