程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> Task Parallel Library02,更進一步,parallellibrary02

Task Parallel Library02,更進一步,parallellibrary02

編輯:C#入門知識

Task Parallel Library02,更進一步,parallellibrary02


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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved