在MVC中使用async和await的說明


首先,在mvc中如果要用純異步請不要使用async和await,可以直接使用Task.Run。

其次,在mvc中使用async和await可以讓系統開新線程處理Task的代碼,同時不必等Task執行結束,就可以同時運行Task之后的代碼,加快效率。

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

/*
 * 演示如何利用 .net 4.5 的新特性實現異步操作
 * 
 * 什么場景下需要異步操作?
 * 在因為磁盤io或網絡io而導致的任務執行時間長的時候應該使用異步操作,如果任務執行時間長是因為cpu的消耗則應使用同步操作(此時異步操作不會改善任何問題)
 * 原理是什么?
 * 在 Web 服務器上,.NET Framework 維護一個用於服務 ASP.NET 請求的線程池(以下把 .NET Framework 維護的用於服務 ASP.NET 請求的線程池稱作為“特定線程池”)
 * 同步操作時,如果特定線程池利用滿了,則不會再提供服務
 * 異步操作時:
 * 1、一個請求過來,特定線程池出一個線程處理此請求
 * 2、啟動一個非特定線程池中的另一個線程處理異步操作,此時處理此請求的線程就會空出來,不會被阻塞,它可以繼續處理其它請求
 * 3、異步操作執行完畢后,從特定線程池中隨便找一個空閑線程返回請求結果
 */

 

實際工作中,async和await我們可以用於類似用戶上傳頭像、上傳照片這種的耗時較長的功能中,我們可以在邊上傳照片時邊處理數據庫的其他事務。

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

如果async和await的異步方法是有返回值的,而且主方法中又要使用這個返回值,那么將不會實現多個異步方法同時執行,要等異步結果后才繼續執行,相當於異步並未起到多程序同時處理事務的目的。這僅是對於Web或控制台程序而言的,如果對於Winform則有大大的不同,因為Winform如果使用異步時界面是可以響應的。

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

所以,在Mvc這種Web界面中使用async和await異步的實際意義就不是很大了,因為界面總是沒有響應的,而且也無法實現多線程同時工作。

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

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: }

 


免責聲明!

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



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