.Net中TaskParallelLibrary的进阶用法


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

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接