Why
在應用程序,尤其是互聯網應用程序中,性能一直是很多大型網站的困擾,由於Web2.0時代的到來,人們更多的把應用程序從C/S結構遷移到B/S結構,這樣會帶來客戶端輕量,部署、試試方便快捷等優勢,但是萬事萬物都有他的兩面性,這樣的發展趨勢同時也帶來了其他方便的不好影響,其中很重要的一項就是系統對服務器的性能要求提高,隨着用戶量增多和系統功能的增加,服務器性能漸漸成了短板。
這種性能的影響,可以從諸多方面進行優化,比如使用負載均衡的服務器,建立服務器集群等方式,但是這是從硬件配置方面的優化,而在軟件開發方面,同樣也可以做很多性能方面的優化。
我們都知道,微軟的IIS服務器中每個線程數量是有限的,在以往的ASP.NET MVC應用程序中,當一個請求到達服務器,IIS從線程池中創建一個線程開始執行調用,當執行完所有的操作將請求返回,再釋放線程,也就是說整個調用過程中,線程是一只持有的。
可如果程序訪問人數增加,線程就成了一種稀缺的資源,如果在一次請求中,需要訪問遠程數據庫、或者進行大的IO處理,這是請求很可能就會長期的持有一個線程,而當用戶量大這種長期請求多的時候,線程池就會迅速的被占滿,請求進入等待隊列,而且等待隊列也是有最大長度的,同時還可能將請求超時返回給瀏覽器端。
所以,我們就會想需要一種異步的方式來執行請求,當遇到長請求的時候,將請求從IIS線程交由后台線程處理,釋放當前線程,處理完成后,再從線程池中選擇線程繼續進行請求的其它處理。
How
在ASP.NET MVC3種,已經提供了AsyncController,可以創建異步的控制器,可那時候需要用到Async和Completed方法對的模式來處理,而現在,我們不需要單獨去實現繼承自AsyncController的類,只需要在原有Action方法上加上特定的關鍵字和返回類型,就可以創建異步的控制器。
而且,在Entity Framework6中,同樣實現了對數據的異步查詢和保存的功能,這就使得我們在應用程序整個過程中,都可以以異步的方式處理邏輯。
Let’s do it
示例使用VS2013創建一個ASP.NET MVC5項目”AsyncExample“(不糾結於設計原則,注意重點)
在Models文件夾中添加一個用戶類:
namespace AsyncExample.Models { public class User { [Key] public int Id { get; set; } public string IdentityToken { get; set; } public string Name { get; set; } } }
給項目添加Entity Framework的引用
PM> install-package entityframework
創建DbContext子類AsyncDbContext類:
namespace AsyncExample.Models { public class AsyncDbContext:DbContext { public DbSet<User> Users { get; set; } public AsyncDbContext() : base("name=DefaultConnection") { } } }
更新Web.config,添加數據庫連接串。
開啟Entity framework的Migrations功能:
PM> enable-migrations
BTW:在新版本的Entity Framework中,已經可以使用自動遷移,不需要為每一次的模型變更手動的去升級數據庫結構,打開的方法很簡單:
打開Migrations文件夾下的Configuration.cs文件,在Configuration默認構造函數中可以看到一個AutomaticMigrationsEnabled屬性被設置為False,改成True就可以自動遷移了,顫抖吧
數據庫更新完之后,來創建一個控制器:
using System.Data.Entity; namespace AsyncExample.Controllers { public class UserController : Controller { AsyncDbContext context = new AsyncDbContext(); public ActionResult Create() { return View(); } [HttpPost] public async Task<ActionResult> Create(User user) { context.Users.Add(user); await context.SaveChangesAsync(); return RedirectToAction("List"); } public async Task<ActionResult> List() { return View(await context.Users.ToListAsync()); } } }
可以看到在Create和List兩個方法中,都使用了async和aswait創建了兩個異步的方法,我們也只直接繼承了Controller,因為現在的同步異步的功能都放在了這個類里,同時我們需要引入Systen.Data.Entity這個命名空間,其中包含了對IQueryable類型的ToListAsync擴展方法,增加了異步加載的功能。
最終呈現效果,擺圖占地:
這篇就到這里了,其實這一系列的下一篇還沒確定要寫什么內容,希望博友基友好朋友們給點意見把。
如果您覺得這篇文章對您有用,勞煩給個贊!
如果您覺得這篇文章可能對別人游泳,勞煩您推薦一個!


