C# 線程知識--使用Task執行異步操作


原文地址:http://www.cnblogs.com/pengstone/archive/2012/12/23/2830238.html

感覺這篇文章不錯,copy了一份;

   在C#4.0之前需要執行一個復雜的異步操作時,只能使用CLR線程池技術來執行一個任務。線程池執行異步任務時,不知道任務何時完成,以及任務的在任務完成后不能獲取到返回值。但是在C#4.0中引人了一個的任務(System.Threading.Tasks命名空間的類型)機制來解決異步操作完成時間和完成后返回值的問題。

1.使用Task類創建並執行簡單任務

通過使用Task的構造函數來創建任務,並調用Start方法來啟動任務並執行異步操作。創建任務時,必須傳遞一個Action或Action<Object>類型的委托回調方法,可以選擇的傳遞任務執行時說需要的數據對象等。Task類的構造函數如下:

 

    public Task(Action action);
        public Task(Action<object> action, object state);
        public Task(Action action, CancellationToken cancellationToken);
        public Task(Action action, TaskCreationOptions creationOptions);
        public Task(Action<object> action, object state, CancellationToken cancellationToken);
        public Task(Action<object> action, object state, TaskCreationOptions creationOptions);
        public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
        public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions);

 

  示例代碼:

 
 static void Main(string[] args)
        {
            //先聲明一個委托
            Console.WriteLine("主線程執行業務處理---開始.");
            Task task = new Task(() =>
            {
                Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作----開始.");
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);
                }
                Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作----結束.");
            });
            task.Start();
            Console.WriteLine("主線程執行其他處理---結束");


            //
            Console.ReadKey(false);
        }

  

  

結果:

主線程執行業務處理---開始.
主線程執行其他處理---結束
使用System.Threading.Tasks.Task執行異步操作----開始.
0
1
2
3
4
5
6
7
8
9
使用System.Threading.Tasks.Task執行異步操作----結束.

 2.等待任務的完成並獲取返回值

使用任務執行異步操作時,最主要的是要后的任務完成時的返回值。在任務類中有一個實例方法Wait(有許多重載版本)他能等待任務的完成,我們也可以通過Task類的派生類Task<TResult>創建一個異步任務,並指定任務完成時返回值的類型,這樣可以通過Task<TResult>的實例對象獲取到任務完成后的返回值。創建一個異步任務並執行0到100求和操作返回最后的計算結果,示例代碼:

Console.WriteLine("主線程執行業務處理---開始.");
            Task<int> task1 = new Task<int>(()=> {
                Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作----開始.");
                int sum = 0;
                for (int i = 0; i < 50; i++)
                {
                    sum += i;
                }
                return sum;
            });
            task1.Start();
            Console.WriteLine("主線程執行其他處理---結束");
            //等待任務的完成執行過程。
            task1.Wait();
            Console.WriteLine("任務執行結果:{0}", task1.Result.ToString());

執行結果:

主線程執行業務處理---開始.
主線程執行其他處理---結束
使用System.Threading.Tasks.Task執行異步操作----開始.
任務執行結果:1225

 Task類還有一些靜態方法,WaitAll用於等待提供的所有 System.Threading.Tasks.Task 對象完成執行過程和Wait用於等待提供的任一個 System.Threading.Tasks.Task 對象完成執行過程,這兩個方法都有一些重載版本。

//等待所有任務完成  
public static void WaitAll(params Task[] tasks);
//等待任意一個任務完成
public static int WaitAny(params Task[] tasks);

  3.使用ContinueWith方法在任務完成時啟動一個新任務

在使用能夠Task類的Wait方法等待一個任務時或派生類的Result屬性獲得任務執行結果都有可能阻塞線程,為了解決這個問題可以使用ContinueWith方法,他能在一個任務完成時自動啟動一個新的任務來處理執行結果。

示例代碼:

 

  Console.WriteLine("主線程執行業務處理---開始.");
            Task<int> task2 = new Task<int>(() => {
                Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作----開始.");
                int sum = 0;
                for (int i = 0; i < 50; i++)
                {
                    sum += i;
                }
                return sum;
            });
            task2.Start();

            Console.WriteLine("主線程執行其他處理---結束");
            task2.ContinueWith(r=>{
                Console.WriteLine("任務執行結果:{0}", r.Result.ToString());
 });

 

  

 

執行結果:

主線程執行業務處理---開始.
主線程執行其他處理---結束
使用System.Threading.Tasks.Task執行異步操作----開始.
任務執行結果:1225

 4.創建父子任務和任務工廠的使用

通過Task類創建的任務是頂級任務,可以通過使用 TaskCreationOptions.AttachedToParent 標識把這些任務與創建他的任務相關聯,所有子任務全部完成以后父任務才會結束操作。示例如下:

   public static void ParentChildTask()
        {
            Task<string[]> parent = new Task<string[]>(state =>
            {
                Console.WriteLine(state);
                string[] result = new string[2];
                //創建並啟動子任務
                new Task(() => { result[0] = "我是子任務1。"; }, TaskCreationOptions.AttachedToParent).Start();
                new Task(() => { result[1] = "我是子任務2。"; }, TaskCreationOptions.AttachedToParent).Start();
                return result;
            }, "我是父任務,並在我的處理過程中創建多個子任務,所有子任務完成以后我才會結束執行");
            parent.ContinueWith(t =>
            {
                Array.ForEach(t.Result, r => Console.WriteLine(r));
            });
            //啟動父任務
            parent.Start();
        }

結果:

我是父任務,並在我的處理過程中創建多個子任務,所有子任務完成以后我才會結束執行
我是子任務1。
我是子任務2。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM