C# Task中的Func, Action, Async與Await的使用

來源:互聯網
上載者:User

標籤:href   images   樣本   測試   很多   自訂   效能   提升   運算式   

在說Asnc和Await之前,先說明一下Func和Action委託, Task任務的基礎的用法

1. Func

Func是一種委託,這是在3.5裡面新增的,2.0裡面我們使用委託是用Delegate,Func位於System.Core命名空間下,使用委託可以提升效率,例如在反射中使用就可以彌補反射所損失的效能。

Action<T>和Func<T,TResult>的功能是一樣的,只是Action<T>沒有返類型,

Func<T,T,Result>:有參數,有傳回型別
Action,則既沒有返回也沒有參數,

Func<T,TResult>
的表現形式分為以下幾種:

1。Func<T,TResult>
2。Func<T,T1,TResult>
3。Func<T,T1,T2,TResult>
4。Func<T,T1,T2,T3,TResult>
5。Func<T,T1,T2,T3,T4,TResult>

分別說一下各個參數的意義,TResult表示
委託所傳回值 所代表的類型, T,T1,T2,T3,T4表示委託所調用的方法的參數類型,

以下是使用樣本:

 1 Func<int, bool> myFunc = null;//全部變數 2  3 myFunc = x => CheckIsInt32(x);  4 //給委託封裝方法的地方 使用了Lambda運算式 5  6 private bool CheckIsInt32(int pars)//被封裝的方法 7 { 8   return pars == 5; 9 }10 11 bool ok = myFunc(5);//調用委託


MSDN:http://msdn.microsoft.com/zh-cn/library/bb534303(VS.95).aspx

2. Action

但是如果我們需要所封裝的方法不傳回值,增麼辦呢?就使用Action!

可以使用
Action<T1, T2, T3, T4>委託以參數形式傳遞方法,而不用顯式聲明自訂的委託。封裝的方法必須與此委託定義的方法簽名相對應。也就是說,封裝的方法必須具有四個均通過值傳遞給它的參數,並且不能傳回值。(在 C# 中,該方法必須返回 void。在 Visual Basic 中,必須通過 Sub…End Sub 結構來定義它。)通常,這種方法用於執行某個操作。

使用方法和Func類似!

Action:既沒有返回,也沒有參數,使用方式如下:

1 Action action = null;//定義action2 3 action =  CheckIsVoid;//封裝方法,只需要方法的名字4 5 action();//調用

 

MSDN:http://msdn.microsoft.com/zh-cn/library/bb548654(VS.95).aspx

總結:

使用Func<T,TResult>和Action<T>,Action而不使用Delegate其實都是為了簡化代碼,使用更少的代碼達到相同的效果,不需要我們顯示的聲明一個委託。

Func<T,TResult>的最後一個參數始終是傳回型別,而Action<T>是沒有傳回型別的,而Action是沒有傳回型別和參數輸入的.

 

3. Task

使用 Async 和 Await 的非同步編程(msdn的好文章) :  https://msdn.microsoft.com/zh-cn/library/hh191443(v=vs.120)

Task基本使用: C# 線程知識--使用Task執行非同步作業

Task和await結合傳回值見: .NET(C#):await返回Task的async方法

Task深入瞭解見: C# Task的使用

 

總結: Task提供一種新的類似多線程的多任務的用法, 達到使用線程的效果,但具體怎麼分配線程由.net底層控制,這樣效能好,效率也高,我們只需要專註商務邏輯, 同時具備以前線程不具備的傳回值的功能(可以通過回調事件來處理),而在Task中只是簡單的使用await來使用, await的task相當於同步的調用task, 同時會有傳回值,只是在書寫方面需要注意async, task,func, action等等關鍵字的使用,新手可能很困惑, 下面的例子就是一個簡單的task使用例子,新手注意注釋!!!

 1 static void Main(string[] args) 2 { 3     //非同步方法呼叫, 當中使用await可以執行task非同步任務,否則當作同步執行 4     test(); 5     //其次輸出,因為非同步進入task任務了,就同步執行當前線程下面的代碼 6     log("Main:調用test後"); 7     Thread.Sleep(Timeout.Infinite);  8 } 9 10 //Main方法不允許加async,所以我們用這個方法使用await11 static async void test()12 {13     //最先輸出,還沒有進入task14     log("test: await之前");15     // await後的內容會被加在目標doo的Task的後面,然後test馬上返回,而doo則是進入了另一個任務執行了16     log("doo的Task的結果: " + await doo());17     // 會等到上面await執行的任務完成後才會執行當前代碼18     log("test: await之後");19 }20 //返回Task的async方法, 一個標準的帶傳回值的非同步task任務方法21 static async Task<int> doo()22 {23     // 簡單的說, async中使用await就是非同步中以同步方式執行Task任務的方法,task任務一個接一個執行.24     var res1 = await Task.Run(() => { Thread.Sleep(1000); log("Awaited Task1 執行"); return 1; });25     var res2 = await Task.Run(() => { Thread.Sleep(1000); log("Awaited Task2 執行"); return 2; });26     var res3 = await Task.Run(() => { Thread.Sleep(1000); log("Awaited Task3 執行"); return 3; });27 28     //不使用await:線程池多線程, 當前task不會等這個執行完,因為不是await,只是又開啟了一個線程29     ThreadPool.QueueUserWorkItem(_ =>30     {31         Thread.Sleep(1000);32         log("ThreadPool.QueueUserWorkItem: 線程池多線程執行");33     });34 35     //不使用await:Task多線程, 當前task不會等這個執行完,因為不是await,只是又開啟了一個任務36     Task.Run(() =>37     {38         Thread.Sleep(1000);39         log("Task.Run: Task多線程執行");40 41     });42    43     return res1 + res2 + res3;44 }45 //輸出方法:顯示當前線程號和輸出資訊46 static void log(string msg)47 {48     Console.WriteLine("線程{0}: {1}", Thread.CurrentThread.ManagedThreadId, msg);49 }

 

執行結果如下:

 

4. Async、Await

這個是.NET 4.5的特性,所以要求最低.NET版本為4.5。

看很多朋友還是使用的Thread來使用非同步多線程操作,基本上看不見有使用Async、Await進行非同步編程的。各有所愛吧,其實都可以。只要正確使用就行,不過還是寫了這篇文章推薦大家使用Async、Await。 原因就是:可以跟寫同步方法一樣去非同步編程。代碼則就非常的清晰,就跟寫普通的代碼一樣,不用關係如何去非同步編程,也讓很多初級程式員也能夠非同步編程了。下面是一個使用Thread 多線程實現的非同步例子,以及一個使用Async與Await的非同步例子,接下來我們再簡單理解下Async與Await的相關技術說明。

Thread多線程非同步編程例子
class Program{    static void Main(string[] args)    {        Console.WriteLine("主線程測試開始..");        Thread th = new Thread(ThMethod);        th.Start();        Thread.Sleep(1000);        Console.WriteLine("主線程測試結束..");        Console.ReadLine();    }      static void ThMethod()    {        Console.WriteLine("非同步執行開始");        for (int i = 0; i < 5; i++)        {            Console.WriteLine("非同步執行" + i.ToString() + "..");            Thread.Sleep(1000);        }        Console.WriteLine("非同步執行完成");    }}

 

  

以上代碼運行效果如

 

 

使用Async與Await進行非同步編程

 

 1 static void Main(string[] args) 2 { 3     Console.WriteLine("主線程測試開始.."); 4     AsyncMethod(); 5     Thread.Sleep(1000); 6     Console.WriteLine("主線程測試結束.."); 7     Console.ReadLine(); 8 } 9 10 static async void AsyncMethod()11 {12     Console.WriteLine("開始非同步代碼");13     var result = await MyMethod();14     Console.WriteLine("非同步代碼執行完畢" + result.ToString());15 }16 17 static async Task<int> MyMethod()18 {19     for (int i = 0; i < 5; i++)20     {21         Console.WriteLine("非同步執行" + i.ToString() + "..");22         await Task.Delay(1000); //類比耗時操作23     }24     return 100;25 }

 

運行效果:

 

顯而易見我們就跟寫同步方法一樣,完成了非同步方法呼叫的編寫,代碼更清晰了。

只有擁有async才能在其內部使用await關鍵字。非同步方法呼叫可以具有Task、Task<>或void的傳回型別;

await關鍵字則是用於傳回值是“可等待”類型(awaitable)的方法

 

C# Task中的Func, Action, Async與Await的使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.