1. 程式人生 > >異步編程

異步編程

cin 暫停 read () 結果 之前 fire src urn

1async/await特性結構
異步方法:就是在處理完成之前就返回到調用方法。
async/await特性結構由三個部分構成:
(1)調用方法:調用異步方法的那個方法,它和異步方法可能在相同的線程,也可能在不同的線程。在異步方法執行其任務的時候繼續執行。
class Program
{
    static void Main()
     {
        ……
        Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6);
         ……
       }
}
(2) 異步方法:有異步標識 async
static
class DoAsyncStuff { public static async Task<int> CalculateSumAsync(int i1,int i2) ----這就是異步方法 有異步標識 async { int sum=await TaskEx.Run( () => GetSum(i1,i2)); return sum; } …… } (3) await 表達式:異步方法內部,指明需要異步執行的任務。一個異步方法至少包含一個await表達式。 2 什麽是異步方法 (1)異步方法 async關鍵字 至少一個await表達式 返回類型:
void Task Task<T> 參數不能為out或ref參數 除了方法以外,Lambda表達式和匿名方法也可以作為異步對象。 Task<T>: 如果調用方法要獲取一個T類型的值,異步方法的返回類型就必須是Task<T>.調用方法將通過讀取Task的Result屬性來獲取這個T類型的值。這個是有返回參數的返回類型 例如: Task<int> value=DoStuff.CalculateSumAsync(5,6); …… Console.WriteLine("Value : {0}",value.Result); Task: 如果調用方法不需要從異步方法中返回某個值,但需要檢查異步方法的狀態,那麽異步方法可以返回一個Task類型的對象。這時,即使異步方法出現了return語句,也不返回任何東西。例如: Task someTask
=DoStuff.CalculateSumAsync(5,6); …… somTask.Wait(); Void:如果調用方法僅僅想執行異步方法,而不需要與它做任何進一步的交互時[這成為[fire and forget]。這時,與上面一樣,即使方法中包含return語句也不會返回任何東西。 Demo:使用返回Task<int> 對象的異步方法 classProgram { staticvoid Main(string[] args) { Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6); Console.WriteLine("Value:{0}", value.Result); } } static async Task<int> CalculateSumAsync(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); return sum; } privatestaticint GetSum(int i1, int i2) { return i1 + i2; } Demo:使用返回Task對象的異步方法 classProgram { staticvoid Main(string[] args) { Task someTask = DoAsyncStuff.CalculateSumAsync1(5, 6); //處理其他事情 someTask.Wait(); Console.WriteLine("Async stuff is done"); Console.ReadLine(); } } publicstaticasyncTask CalculateSumAsync1(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); Console.WriteLine("Value:{0}", sum); } privatestaticint GetSum(int i1, int i2) { return i1 + i2;} Demo:使用返回void的異步方法 staticvoid Main(string[] args) { DoAsyncStuff.CalculateSumAsync2(5, 6); //處理其他事情 Thread.Sleep(200);----如果這裏不暫停當前線程,則會先輸出Program Exiting,在輸出11 Console.WriteLine("Program Exiting"); } publicstaticasyncvoid CalculateSumAsync2(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); Console.WriteLine("Value:{0}", sum); } privatestaticint GetSum(int i1, int i2) {return i1 + i2; } 當程序運行到異步方法內部的await表達式時,異步方法會立即創建一個返回類型Task或Task<T>的對象,並返回給調用方法。 調用方法使用Task對象,取其Result屬性時,如果異步方法還沒有設置該屬性,調用方法就暫停等待。 (2)異步方法控制流: 技術分享 privateasyncTask<int> CountCharactersAsync(string uriString) { WebClient wc = newWebClient(); string result = await wc.DownloadStringTaskAsync(uriString); return result.Length; } 上面的異步方法,在遇到await時會立即返回,返回的這個類型與await表達式本身的內容沒有關系,會創建一個異步方法返回類型的對象,即Task<int>對象。而異步方法的return語句並沒有真正返回某個值,只是退出了。 (3)await表達式 .net 4.5,有大量的異步方法在BCL中。比如上面的DownloadStringTaskAsync方法等。 也可以自己編寫異步方法: 使用Task.Run()方法,這個方法是在不同的線程上運行你的方法。 Task.Run的簽名:Task Run(Func<TReturn> func) 因此定義異步方法,最重要的就是要創建一個委托。 Demo:使用Task.Run定義await表達式,進而定義異步方法。 classMyClass { publicint Get10() { return 10; } publicasyncTask DoWorkAsync() { Func<int> ten = newFunc<int>(Get10); int a = awaitTask.Run(ten); int b = awaitTask.Run(newFunc<int>(Get10)); int c = awaitTask.Run(() => { return 10; });//該Lambda表達式是與Func<int>兼容的將隱式轉換為該委托 Console.WriteLine("{0} {1} {2}", a, b, c); } } staticvoid Main(string[] args) { Task t = (newMyClass()).DoWorkAsync(); Console.WriteLine("111"); t.Wait(); Console.WriteLine("222"); } 結果: 技術分享 Task.Run: 技術分享
技術分享
技術分享
4)取消一個異步操作 技術分享5)異常處理與await表達式 Task t t.Satus t.IsFaulted (6)在調用方法中同步的等待任務 wait() t.Wait(); Task.WaitAll(); Task.WaitAny(); 技術分享 (7)在異步方法中異步的等待任務 技術分享 異步等待所有tasks中的任務完成,不會占用主線程的時間。

異步編程