Archiv der Kategorie: AJAX

Blokierende Parallele AJAX Requests und ASP.NET


Bis gestern dachte ich eigentlich das ich mich in ASP.NET ganz gut auskenne, aber da wollte es mir ASP.NET mal wieder richtig zeigen, das man auch hier nie auslernt. Denn wenn man mehrere AJAX Requests parallel startet um die Daten für einen View asynchron zu laden und in einem der Requests in die Session schreibt, dann werden die AJAX Requests zwar laut Browser zum gleichen Zeitpunkt abgeschickt, aber von ASP.NET der Reihe nach abgearbeitet und nicht parallel. Diese Problematik tritt auch nur dann auf wenn man in die Session schreibt.

1. Das Beispiel ohne Sessionzugriff – hier funktioniert alles wie erwartet

//Controller Code

public JsonResult LoadTodoItem(int todoItemId)
{
    System.Threading.Thread.Sleep(2000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

public JsonResult LoadTodoItem2(int todoItemId)
{
    System.Threading.Thread.Sleep(4000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

public JsonResult LoadTodoItem3(int todoItemId)
{
    System.Threading.Thread.Sleep(6000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

TypeScript (Angular) Aufruf für diese Funktionen

 init() : void {
     this.todoSrv.loadTodoItem(this.todoId).then((result: My.ITodoCreateViewModel) => {
         this.viewModel = result;
     });
     this.todoSrv.loadTodoItem2(this.todoId).then((result: My.ITodoCreateViewModel) => {
         this.viewModel = result;
     });
     this.todoSrv.loadTodoItem3(this.todoId).then((result: My.ITodoCreateViewModel) => {
         this.viewModel = result;
     });
 }

Das Zeitdiagramm im Browser beim Aufrufen:

image

2. Beispiel mit dem Zugriff auf die Session im Controller – keine Parallele Verarbeitung in ASP.NET

Hier ändert sich nur der Controller um den Sessionzugriff, aber nicht der Aufruf im TypeScript (Angular).

public JsonResult LoadTodoItem(int todoItemId)
{
    Session["test"] = "blubb";
    System.Threading.Thread.Sleep(2000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

public JsonResult LoadTodoItem2(int todoItemId)
{
    System.Threading.Thread.Sleep(4000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

public JsonResult LoadTodoItem3(int todoItemId)
{
    System.Threading.Thread.Sleep(6000);
    return Json(TodoCreateModelBuilder.LoadTodoItem(todoItemId), JsonRequestBehavior.AllowGet);
}

Dabei ist zu beachten, wenn man auf die Controller Funktionen das erste mal zugreift, dann hat man ein Ablaufdiagramm wie oben und man “denkt” es hat alles geklappt. Wenn man dann aber auf die Funktionen ein zweites mal zugreift, dann kommt es zu dem hier dargestellten Ablaufdiagramm, in dem man schön sehen kann das sich die Zeiten addieren und nicht mehr parallel ablaufen. Obwohl das Zeitdiagramm des Browsers dies anders suggeriert, denn hier starten alle Aufrufe parallel.

image

Wenn man von diesem Laufzeitverhalten aber noch nie etwas gehört hat, dann kann die Suche hier schon etwas Zeit in Anspruch nehmen. Natürlich gibt es auch für dieses Problem eine Lösung und nachdem ich wusste wo das Problem liegt habe ich auch schnell Artikel im Netz dazu gefunden:

http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/

http://www.stefanprodan.com/2012/02/parallel-processing-of-concurrent-ajax-requests-in-asp-net-mvc/

http://weblogs.asp.net/imranbaloch/concurrent-requests-in-asp-net-mvc

Advertisements