在MVC中使用async和await的說明

首先,在mvc中若是要用純異步請不要使用async和await,能夠直接使用Task.Run。web

其次,在mvc中使用async和await可讓系統開新線程處理Task的代碼,同時沒必要等Task執行結束,就能夠同時運行Task以後的代碼,加快效率。數據庫

要注意的是:若是使用async和await,系統雖然能夠同時處理多個事務,但客戶端(瀏覽器)不會有響應,依然要等到全部代碼所有執行完畢(包括異步的代碼)才能正常響應。編程

/*
 * 演示如何利用 .net 4.5 的新特性實現異步操做
 * 
 * 什麼場景下須要異步操做?
 * 在由於磁盤io或網絡io而致使的任務執行時間長的時候應該使用異步操做,若是任務執行時間長是由於cpu的消耗則應使用同步操做(此時異步操做不會改善任何問題)
 * 原理是什麼?
 * 在 Web 服務器上,.NET Framework 維護一個用於服務 ASP.NET 請求的線程池(如下把 .NET Framework 維護的用於服務 ASP.NET 請求的線程池稱做爲「特定線程池」)
 * 同步操做時,若是特定線程池利用滿了,則不會再提供服務
 * 異步操做時:
 * 一、一個請求過來,特定線程池出一個線程處理此請求
 * 二、啓動一個非特定線程池中的另外一個線程處理異步操做,此時處理此請求的線程就會空出來,不會被阻塞,它能夠繼續處理其它請求
 * 三、異步操做執行完畢後,從特定線程池中隨便找一個空閒線程返回請求結果
 */

 

實際工做中,async和await咱們能夠用於相似用戶上傳頭像、上傳照片這種的耗時較長的功能中,咱們能夠在邊上傳照片時邊處理數據庫的其餘事務。瀏覽器

而純異步則多用於時間較長,而無需結果實時看反饋給用戶的操做,例如:管理在後臺備份數據庫、清理垃圾文件等。服務器

若是async和await的異步方法是有返回值的,並且主方法中又要使用這個返回值,那麼將不會實現多個異步方法同時執行,要等異步結果後才繼續執行,至關於異步並未起到多程序同時處理事務的目的。這僅是對於Web或控制檯程序而言的,若是對於Winform則有大大的不一樣,由於Winform若是使用異步時界面是能夠響應的。網絡

Web中異步更多的是用來實現大量IO操做,或大量調用WCF、WebService時使用。多線程

因此,在Mvc這種Web界面中使用async和await異步的實際意義就不是很大了,由於界面老是沒有響應的,並且也沒法實現多線程同時工做。mvc

有須要請看這篇:http://www.dozer.cc/2012/03/async-and-await-in-web-application/app

async的做用是異步執行,await的做用是等待執行結果(會卡住異步方法中await如下的代碼,但不會卡死主線程)。
異步

async通常最終都須要一個async void方法來進行最高層的調用。好比:private async void Sync_Button_Click(object sender, RoutedEventArgs e),C#中也提供了大量的可設置async的系統方法和事件。

 

class Program  
{  
    private static async void Test()  
    {  
        Task<int> t = new Task<int>(() => { Thread.Sleep(3000); return 1; });  
        t.Start();  
        int tr = await t;  
        Console.WriteLine(tr);  
    }  
  
    static void Main(string[] args)  
    {  
        Test();  
        Console.WriteLine("Main");  
        Console.ReadKey();  
    }  
}  

 Test函數就用最簡單的方法使用了這兩個關鍵字,執行這段代碼,首先輸出「Main」,而後3秒鐘後會輸出「1」。

 也可使用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            Test();
            Console.WriteLine("Main");
            Console.ReadKey(); 
        }

        private static async void Test()
        {
            var t = Task<int>.Run(() => { Thread.Sleep(3000); return 1; });
            Console.WriteLine(await t);
        }  
    }
}

 

使用async異步編程時,請注意以下事項:

    1. async void 函數只能在UI Event回調中使用。
    2. async void 函數中必定要用try-catch捕獲全部異常,不然會很容易致使程序崩潰。
    3. async void 類型的lambda表達式很是隱蔽,而且容易在無心中編寫出來,尤爲須要注意。
    4. 不要忽視CS4014告警,更不要爲了消除CS4014告警而改用 async void 函數。
      確實無需等待的
      async Task 函數用我前面寫的擴展函數 IgnorCompletion 消除 這個告警。
    5. 註冊 TaskScheduler.UnobservedTaskException事件 ,記錄Task中未處理異常信息,方便分析及錯誤定位。(注意,這個回調裏面不能進行耗時操做,具體緣由參看前面的老趙的那篇Blog)
private async void Sync_Button_Click(object sender, RoutedEventArgs e) {
   2:     OutputTextBlock.Text += "開始" + Environment.NewLine;
   3:     // 這裡會等 getFileContentAsync() 執行完畢後, 再執行貼上結束字串那一行
   4:     // 因為 Compiler 會再 await 這行下斷點
   5:     OutputTextBlock.Text += await getFileContentAsync();
   6:     OutputTextBlock.Text += "結束" + Environment.NewLine;
   7: }
   8:  
   9: private async Task<string> getFileContentAsync() {
  10:     StorageFolder folder = KnownFolders.DocumentsLibrary;
  11:     StorageFile file = await folder.GetFileAsync(TESTED_FILE_NAME);
  12:     var result = await FileIO.ReadTextAsync(file) + Environment.NewLine;
  13:     return result;
  14: }
相關文章
相關標籤/搜索