ASP.NET MVC 4 Sürümünde Zaman Uyumsuz Metotlar Kullanma

Rick Anderson tarafından

Bu öğretici, Microsoft Visual Studio ücretsiz bir sürümü olan Web için Visual Studio Express 2012kullanarak zaman uyumsuz BIR ASP.NET MVC web uygulaması oluşturma hakkında temel bilgileri öğretir. Visual Studio 2012' i de kullanabilirsiniz.

Bu öğretici için GitHub 'da bir örnek verilmiştir https://github.com/RickAndMSFT/Async-ASP.NET/

.Net 4,5 birleşimi IÇINDEKI ASP.NET MVC 4 Denetleyici sınıfı, görev<ActionResult>türünde bir nesne döndüren zaman uyumsuz eylem yöntemleri yazmanızı sağlar. .NET Framework 4, görev olarak adlandırılan bir zaman uyumsuz programlama kavramı sunmuştur ve ASP.NET MVC 4 görevidestekler. Görevler, görev türü ve System. Threading. Tasks ad alanındaki ilgili türler tarafından temsil edilir. .NET Framework 4,5, görev nesneleriyle çalışmayı önceki zaman uyumsuz yaklaşımlardan çok daha az karmaşık olan await ve Async anahtar sözcükleriyle bu zaman uyumsuz destek üzerinde oluşturulur. Await anahtar sözcüğü, kod parçasının zaman uyumsuz olarak başka bir kod parçasına beklemesi gerektiğini belirten sözdizimsel bir toplu özelliktir. Async anahtar sözcüğü, yöntemleri görev tabanlı zaman uyumsuz yöntemler olarak işaretlemek için kullanabileceğiniz bir ipucunu temsil eder. Await, Asyncve Task nesnesinin birleşimi, .NET 4,5 'e zaman uyumsuz kod yazmanızı çok daha kolay hale getirir. Zaman uyumsuz yöntemlere yönelik yeni model görev tabanlı zaman uyumsuz model (tap) olarak adlandırılır. Bu öğreticide, await ve Async anahtar sözcüklerini ve görev ad alanını kullanarak zaman uyumsuz programlama hakkında bazı benzerlik olduğunu varsaymaktadır.

Await ve Async anahtar sözcüklerini ve görev ad alanını kullanma hakkında daha fazla bilgi için aşağıdaki başvurulara bakın.

Isteklerin Iş parçacığı havuzu tarafından nasıl Işlendiği

Web sunucusunda .NET Framework, ASP.NET isteklerine hizmet vermek için kullanılan iş parçacıklarının havuzunu tutar. Bir istek geldiğinde, bu isteği işlemek için havuzdan bir iş parçacığı gönderilir. İstek zaman uyumlu olarak işleniyorsa, istek işlenirken isteği işleyen iş parçacığı meşgul olur ve bu iş parçacığı başka bir isteğe hizmet edemez.

İş parçacığı havuzu çok sayıda meşgul iş parçacığına uyum sağlayacak kadar büyük hale getirilbildiğinden bu bir sorun olmayabilir. Ancak, iş parçacığı havuzundaki iş parçacıklarının sayısı sınırlıdır (.NET 4,5 için varsayılan en yüksek 5.000 ' dir). Uzun süreli çok sayıda istek olan büyük uygulamalarda, kullanılabilir tüm iş parçacıkları meşgul olabilir. Bu koşul, iş parçacığı başlangıçadı olarak bilinir. Bu koşula ulaşıldığında, Web sunucusu istekleri sıralar. İstek sırası dolarsa, Web sunucusu istekleri HTTP 503 durumu (sunucu çok meşgul) ile reddeder. CLR iş parçacığı havuzunda yeni iş parçacığı kısıtlamalarıyla ilgili sınırlamalar vardır. Eşzamanlılık burstise (yani, Web siteniz çok fazla sayıda istek alabilir) ve yüksek gecikme süresine sahip arka uç çağrıları nedeniyle tüm kullanılabilir istek iş parçacıkları meşgul olur, sınırlı iş parçacığı ekleme oranı uygulamanızın yanıt vermesini çok kötü hale getirir. Ayrıca, iş parçacığı havuzuna eklenen her yeni iş parçacığının ek yükü vardır (1 MB yığın bellek gibi). Zaman uyumlu yöntemler kullanan bir Web uygulaması iş parçacığı havuzunun .NET 4,5 varsayılan en yüksek değeri olan 5 ' e kadar büyüdüğü yüksek gecikme süreli çağrılara hizmet verebilir zaman uyumsuz yöntemler ve yalnızca 50 iş parçacığı. Zaman uyumsuz iş yaparken her zaman bir iş parçacığı kullanmıyoruz. Örneğin, zaman uyumsuz bir Web hizmeti isteği yaptığınızda, ASP.NET zaman uyumsuz Yöntem çağrısı ve awaitarasında herhangi bir iş parçacığı kullanmaz. İş parçacığı havuzunun yüksek gecikme süresine sahip isteklere kullanımı, büyük bir bellek parmak izine ve sunucu donanımının kötü kullanımına neden olabilir.

Zaman uyumsuz Istekleri işleme

Başlangıçta çok sayıda eşzamanlı istek sunan veya bir bursty yüküne sahip olan bir Web uygulamasında (eşzamanlılık aniden arttığında), Web hizmeti çağrılarının zaman uyumsuz yapılması uygulamanın yanıt hızını arttırır. Zaman uyumsuz bir istek, zaman uyumlu bir istek olarak işlemek için aynı süreyi alır. İstek iki saniyelik bir Web hizmeti çağrısı yapıyorsa, istek zaman uyumlu veya zaman uyumsuz olarak yapılıp yapılmadıklarında iki saniye sürer. Ancak zaman uyumsuz bir çağrı sırasında, bir iş parçacığının, ilk isteğin tamamlanmasını beklediği sırada diğer isteklere yanıt vermemesi engellenmez. Bu nedenle, uzun süre çalışan işlemleri çağıran çok sayıda eşzamanlı istek olduğunda zaman uyumsuz istekler istek sıraya alma ve iş parçacığı havuzunun büyümesini önler.

Zaman uyumlu veya zaman uyumsuz eylem yöntemleri seçme

Bu bölümde, zaman uyumlu veya zaman uyumsuz eylem yöntemlerinin ne zaman kullanılacağı hakkındaki yönergeler listelenmiştir. Bunlar yalnızca kılavuzlardır; zaman uyumsuz yöntemlerin performansla yardım edilip edilmeyeceğini öğrenmek için her uygulamayı ayrı ayrı inceleyin.

Genel olarak, aşağıdaki koşullar için zaman uyumlu yöntemleri kullanın:

  • İşlemler basit veya kısa çalışıyor.
  • Basitlik, verimlilik açısından daha önemlidir.
  • İşlemler, yoğun disk veya ağ yükü içeren işlemler yerine öncelikle CPU operasyonlardır. CPU 'ya bağlı işlemlerde zaman uyumsuz eylem yöntemlerinin kullanılması, hiçbir avantaj sağlamaz ve daha fazla yüke neden olur.

Genel olarak, aşağıdaki koşullar için zaman uyumsuz yöntemleri kullanın:

  • Zaman uyumsuz yöntemler aracılığıyla tüketilen hizmetleri arıyorsanız ve .NET 4,5 veya üzeri bir sürümü kullanıyorsunuz.
  • İşlemler, CPU ile bağlantılı olarak ağ bağlantılı veya g/ç-bağlantılı.
  • Paralellik, kod basitliği dışında daha önemlidir.
  • Kullanıcıların uzun süre çalışan bir isteği iptal etmelerini sağlayan bir mekanizma sağlamak istiyorsunuz.
  • İş parçacıklarını anahtarlama avantajı, bağlam anahtarı maliyetini ortaya çıktı. Genel olarak, zaman uyumlu yöntem ASP.NET istek iş parçacığı üzerinde bekliyorsa bir yöntemi zaman uyumsuz yapmanız gerekir. Çağrıyı zaman uyumsuz yaparak, ASP.NET istek iş parçacığı, Web hizmeti isteğinin tamamlanmasını beklerken hiçbir iş yapılmaz.
  • Test, engelleme işlemlerinin site performansı açısından bir performans sorunu olduğunu ve IIS 'nin bu engelleme çağrıları için zaman uyumsuz yöntemleri kullanarak daha fazla istek hizmet verebilir olduğunu gösterir.

İndirilebilir örnek, zaman uyumsuz eylem yöntemlerinin etkin bir şekilde nasıl kullanılacağını gösterir. Belirtilen örnek, .NET 4,5 kullanılarak ASP.NET MVC 4 ' te zaman uyumsuz programlama basit bir gösterimi sağlamak üzere tasarlanmıştır. Örnek, ASP.NET MVC 'de zaman uyumsuz programlama için başvuru mimarisi olmak üzere tasarlanmamıştır. Örnek program, görevi çağıran ASP.NET Web API yöntemlerini çağırır. uzun süre çalışan Web hizmeti çağrılarına benzetim yapmak için gecikme . Çoğu üretim uygulaması, zaman uyumsuz eylem yöntemlerinin kullanımı için bu tür açık avantajları göstermez.

Birkaç uygulama tüm eylem yöntemlerinin zaman uyumsuz olmasını gerektirir. Genellikle, birkaç zaman uyumlu eylem yönteminin zaman uyumsuz yöntemlere dönüştürülmesi, gereken iş miktarı için en iyi verimlilik artışı sağlar.

Örnek uygulama

Örnek uygulamayı GitHub sitesindeki https://github.com/RickAndMSFT/Async-ASP.NET/ indirebilirsiniz. Depo üç projeden oluşur:

  • Mvc4Async: Bu öğreticide kullanılan kodu IÇEREN ASP.NET MVC 4 projesi. WebAPIpgw HIZMETINE Web API çağrıları yapar.
  • WebAPIpgw: Products, Gizmos and Widgets denetleyicilerini uygulayan ASP.NET MVC 4 Web API projesi. WebAppAsync projesi ve Mvc4Async projesi için verileri sağlar.
  • WebAppAsync: ASP.NET Web Forms projesi başka bir öğreticide kullanılır.

Şeyler Synchronous ACTION yöntemi

Aşağıdaki kod, bir şeyler listesini göstermek için kullanılan zaman uyumlu Gizmos eylem yöntemini gösterir. (Bu makale için, Gizmo kurgusal bir makine aygıtıdır.)

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}

Aşağıdaki kod, Gizmo hizmetinin GetGizmos yöntemini gösterir.

public class GizmoService
{
    public async Task<List<Gizmo>> GetGizmosAsync(
        // Implementation removed.
       
    public List<Gizmo> GetGizmos()
    {
        var uri = Util.getServiceUri("Gizmos");
        using (WebClient webClient = new WebClient())
        {
            return JsonConvert.DeserializeObject<List<Gizmo>>(
                webClient.DownloadString(uri)
            );
        }
    }
}

GizmoService GetGizmos yöntemi bir URI 'yi bir ASP.NET Web API HTTP hizmetine geçirir ve bu, şeyler verilerinin bir listesini döndürür. WebAPIpgw projesi, Web API gizmos, widget ve product denetleyicilerinin uygulamasını içerir.
Aşağıdaki görüntüde örnek projeden şeyler görünümü gösterilmektedir.

Şeyler

Zaman uyumsuz şeyler Action yöntemi oluşturma

Örnek, zaman uyumsuz programlama için gereken karmaşık dönüştürmeleri sürdürmekten önce derleyicinin sorumlu olmasını sağlamak için yeni Async ve await anahtar sözcüklerini (.NET 4,5 ve Visual Studio 2012 ' de kullanılabilir) kullanır. Derleyici, zaman uyumlu denetim akış yapılarını kullanarak C#kod yazmanızı sağlar ve derleyici, iş parçacıklarını engellemeyi önlemek için geri çağırmaları kullanmak için gereken dönüştürmeleri otomatik olarak uygular.

Aşağıdaki kod, zaman uyumlu Gizmos yöntemi ve GizmosAsync zaman uyumsuz yöntemi gösterir. Tarayıcınız HTML 5 <mark> öğesinidestekliyorsa, GizmosAsync değişiklikleri sarı vurgulamada görürsünüz.

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}
public async Task<ActionResult> GizmosAsync()
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", await gizmoService.GetGizmosAsync());
}

GizmosAsync zaman uyumsuz olarak izin vermek için aşağıdaki değişiklikler uygulandı.

  • Yöntemi Async anahtar sözcüğüyle işaretlenir, bu da derleyiciye gövdenin parçaları için geri çağrılar oluşturmasını ve döndürülen bir Task<ActionResult> otomatik olarak oluşturmasını söyler.
  • "zaman uyumsuz" metot adına eklendi. "Async" eklenmesi gerekli değildir, ancak zaman uyumsuz yöntemler yazılırken kuralıdır.
  • Dönüş türü, ActionResult Task<ActionResult>olarak değiştirildi. Task<ActionResult> dönüş türü, devam eden çalışmayı temsil eder ve zaman uyumsuz işlemin tamamlanmasını beklemek için bir tanıtıcı ile metodun çağıranlarını sağlar. Bu durumda, çağıran Web hizmetidir. Task<ActionResult>, ActionResult. sonucuyla devam eden işi temsil eder
  • Await anahtar sözcüğü Web hizmeti çağrısına uygulandı.
  • Zaman uyumsuz Web hizmeti API 'SI çağrıldı (GetGizmosAsync).

GetGizmosAsync yönteminin içinde başka bir zaman uyumsuz yöntem GetGizmosAsync çağırılır. GetGizmosAsync hemen, veriler kullanılabilir olduğunda sonunda tamamlanacak bir Task<List<Gizmo>> döndürür. Gizmo verilerine sahip olana kadar başka bir şey yapmak istemediğiniz için, kod görevi bekler ( await anahtar sözcüğünü kullanarak). Await anahtar sözcüğünü yalnızca Async anahtar sözcüğüyle açıklama eklenen yöntemlerde kullanabilirsiniz.

Await anahtar sözcüğü, görev tamamlanana kadar iş parçacığını engellemez. Görevin geri kalanını görevde geri çağırma olarak imzalar ve hemen döndürür. Beklenen görev sonunda tamamlandığında, bu geri aramayı çağırır ve bu nedenle, yöntemin hemen kapandığı yerde yürütmeye devam eder. Await ve Async anahtar sözcüklerini ve görev ad alanını kullanma hakkında daha fazla bilgi için bkz. Async References.

Aşağıdaki kod, GetGizmos ve GetGizmosAsync yöntemlerini göstermektedir.

public List<Gizmo> GetGizmos()
{
    var uri = Util.getServiceUri("Gizmos");
    using (WebClient webClient = new WebClient())
    {
        return JsonConvert.DeserializeObject<List<Gizmo>>(
            webClient.DownloadString(uri)
        );
    }
}
public async Task<List<Gizmo>> GetGizmosAsync()
{
    var uri = Util.getServiceUri("Gizmos");
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }
}

Zaman uyumsuz değişiklikler, yukarıdaki GizmosAsync yapılan değişikliklerle benzerdir.

  • Yöntem imzasına zaman uyumsuz anahtar sözcüğüyle açıklama eklendi, dönüş türü Task<List<Gizmo>>olarak değiştirildi ve zaman uyumsuz Yöntem adına eklenmiş.
  • , WebClient sınıfı yerine zaman uyumsuz HttpClient sınıfı kullanılır.
  • Await anahtar sözcüğü HttpClient zaman uyumsuz yöntemlerine uygulandı.

Aşağıdaki görüntüde zaman uyumsuz Gizmo görünümü gösterilmektedir.

async

Şeyler verilerinin tarayıcılar sunumu, zaman uyumlu çağrı tarafından oluşturulan görünümle aynıdır. Tek fark, zaman uyumsuz sürümdür ağır yüklerin altında daha performanslı olabilir.

Paralel olarak birden çok Işlem gerçekleştirme

Zaman uyumsuz eylem yöntemlerinin, bir eylemin birkaç bağımsız işlem gerçekleştirmesi gerektiğinde zaman uyumlu yöntemlerle önemli bir avantajı vardır. Belirtilen örnekte, zaman uyumlu Yöntem PWG(ürünler, pencere öğeleri ve şeyler için), ürünlerin, pencere öğelerinin ve şeyler 'in bir listesini almak için üç Web hizmeti çağrısının sonuçlarını görüntüler. Bu hizmetleri sağlayan ASP.NET Web API projesi, görevi kullanır . gecikme veya yavaş ağ çağrılarının benzetimini yapmak için gecikme. Gecikme 500 milisaniyeye ayarlandığında, zaman uyumsuz PWGasync yöntemi, zaman uyumlu PWG sürümü 1.500 milisaniyeye göre daha fazla 500 milisaniyelik sürer. Zaman uyumlu PWG yöntemi aşağıdaki kodda gösterilmiştir.

public ActionResult PWG()
{
    ViewBag.SyncType = "Synchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var pwgVM = new ProdGizWidgetVM(
        widgetService.GetWidgets(),
        prodService.GetProducts(),
        gizmoService.GetGizmos()
       );

    return View("PWG", pwgVM);
}

Zaman uyumsuz PWGasync yöntemi aşağıdaki kodda gösterilmiştir.

public async Task<ActionResult> PWGasync()
{
    ViewBag.SyncType = "Asynchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var widgetTask = widgetService.GetWidgetsAsync();
    var prodTask = prodService.GetProductsAsync();
    var gizmoTask = gizmoService.GetGizmosAsync();

    await Task.WhenAll(widgetTask, prodTask, gizmoTask);

    var pwgVM = new ProdGizWidgetVM(
       widgetTask.Result,
       prodTask.Result,
       gizmoTask.Result
       );

    return View("PWG", pwgVM);
}

Aşağıdaki görüntüde, Pwgasync yönteminden döndürülen görünüm gösterilmektedir.

pwgAsync

Iptal belirteci kullanma

Task<ActionResult>döndüren zaman uyumsuz eylem yöntemleri iptal edilir ve bu, AsyncTimeout özniteliğiyle birlikte sağlandığında bir CancellationToken parametresi alırlar. Aşağıdaki kod, 150 milisaniye zaman aşımı ile GizmosCancelAsync yöntemini gösterir.

[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
                                    View = "TimeoutError")]
public async Task<ActionResult> GizmosCancelAsync(
                       CancellationToken cancellationToken )
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos",
        await gizmoService.GetGizmosAsync(cancellationToken));
}

Aşağıdaki kod, CancellationToken parametresini alan GetGizmosAsync aşırı yüklemesini gösterir.

public async Task<List<Gizmo>> GetGizmosAsync(string uri,
    CancellationToken cancelToken = default(CancellationToken))
{
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri, cancelToken);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }
}

Belirtilen örnek uygulamada, Iptal belirteci demo bağlantısını seçtiğinizde GizmosCancelAsync yöntemi çağrılıyordu ve zaman uyumsuz çağrının iptali gösterilmektedir.

Yüksek eşzamanlılık/yüksek gecikmeli Web hizmeti çağrıları için sunucu yapılandırması

Zaman uyumsuz bir Web uygulamasının avantajlarını gerçekleştirmek için, varsayılan sunucu yapılandırmasında bazı değişiklikler yapmanız gerekebilir. Zaman uyumsuz Web uygulamanızı yapılandırırken ve stres testi yaparken aşağıdakileri aklınızda bulundurun.

  • Windows 7, Windows Vista ve tüm Windows istemci işletim sistemlerinde en fazla 10 eşzamanlı istek vardır. Yüksek yük altında zaman uyumsuz yöntemlerin avantajlarını görmek için bir Windows Server işletim sistemi gerekir.

  • .NET 4,5 ' i yükseltilmiş bir komut isteminden IIS ile kaydedin:
    %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regııs-ı
    Bkz . asp.NET IIS Kayıt Aracı (Aspnet_regııs. exe)

  • Http. sys kuyruk sınırını 1.000 varsayılan değerinden 5.000 ' e artırmanız gerekebilir. Ayar çok düşükse, http 503 durumu ile http. sys Red isteklerini görebilirsiniz. HTTP. sys kuyruk sınırını değiştirmek için:

    • IIS Yöneticisi 'ni açın ve uygulama havuzları bölmesine gidin.
    • Hedef uygulama havuzuna sağ tıklayın ve Gelişmiş ayarlar' ı seçin.
      gelişmiş
    • Gelişmiş ayarlar Iletişim kutusunda sıra uzunluğu değerini 1.000 5.000 olarak değiştirin.
      kuyruğu uzunluğu

    Yukarıdaki görüntülerde, uygulama havuzu .NET 4,5 kullanıyor olsa da, .NET Framework 'ün v 4.0 olarak listelendiğini göz önünde bulunur. Bu tutarsızlığı anlamak için aşağıdakilere bakın:

  • Uygulamanız HTTP üzerinden bir arka uçta iletişim kurmak için Web Hizmetleri veya System.NET kullanıyorsa, connectionManagement/maxconnection öğesini artırmanız gerekebilir. ASP.NET uygulamaları için bu, otomatik yapılandırma özelliği tarafından CPU sayısının 12 katı ile sınırlıdır. Yani, bir dört proc üzerinde en fazla 12 * 4 = 48 bir IP uç noktasına eşzamanlı bağlantı sağlayabilirsiniz. Bu, Otomatikolarak bağlı olduğundan, bir ASP.NET uygulamasında maxconnection artırmanın en kolay yolu, System .net. ServicePointManager. DefaultConnectionLimit ' i global. asax dosyasındaki from Application_Start yönteminde Program aracılığıyla ayarlamaya yönelik bir yöntemdir. Örnek için bkz. örnek indirme.

  • .NET 4,5 ' de, maxConcurrentRequestsPerCPU için 5000 varsayılan değer iyi olmalıdır.