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

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

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;//定義action
2 
3 action =  CheckIsVoid;//封裝方法,只須要方法的名字
4 
5 action();//調用

 

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

總結:

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

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

 

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,因此咱們用這個方法使用await
11 static async void test()
12 {
13     //最早輸出,尚未進入task
14     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)的方法

相關文章
相關標籤/搜索