ASP.NET - Asincronismo

Le tecniche di asincronismo (da non scambiare con AJAX) sono delle tecniche che possono tornarci in auto sopratutto per quelle pagine che richiedono molto tempo nell'acquisizione dei dati.

La logica è quella di spostare il codice che richiede molto tempo, dal thread di ASP.NET ad un thread non ASP.NET.
La pagina verrà comunque servita all'utente con la stessa tempistica di una pagina sincrona.

Perchè l'asincronismo?
ASP.NET può gestire 20 Threads, per ogni thread può gestire una Request Queue di 1000 richieste, se non avremo più risorse riceveremo un 503 – Service Unavailable.

Quello che facciamo noi è liberare il prima possibile uno dei 20 thread durante una fase time-consuming.

Ci sono vari modi per lavorare con l'asincronismo quello che vedremo adesso è asynchronous pages.

L'ipotesi, abbastanza accreditabile, è un'applicazione ASP.NET che richiede dei dati ad un servizio WCF il quale perderà del tempo prima di rispondere.

Per prima cosa, per poter attivare l'asincronismo, dobbiamo inserire il seguente attributo nella direttiva Page della nostra pagina:

Async="true"

Adesso aggiungiamo un Web Service al nostro progetto e inseriamo del codice che richiede del tempo per esser eseguito:

        [WebMethod]
        public string GetDataWithDelay(int delay)
        {
            if (delay > 0)
                Thread.Sleep(delay * 1000);
            return "Dati di ritorno dal metodo GetDataWithDelay";
        }

Adesso aggiungiamo un Web Reference al nostro progetto, specificando il web server appena creato. Fatto questo lo utilizzeremo nostra pagina ASP.NET:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1._Default" Async="true" Trace="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="" />
     </div>
    </form>
</body>
</html>
        protected void Page_Load(object sender, EventArgs e)
        {
            localhost.WebService1 ws1 = new localhost.WebService1();
            ws1.GetDataCompleted += new WebApplication1.localhost.GetDataCompletedEventHandler(ws1_GetDataCompleted);
            ws1.GetDataAsync(3);
            Trace.Warn(Thread.CurrentThread.ManagedThreadId.ToString());
        }

        void ws1_GetDataCompleted(object sender, WebApplication1.localhost.GetDataCompletedEventArgs e)
        {
            Label1.Text = e.ToString();
            Trace.Warn(Thread.CurrentThread.ManagedThreadId.ToString());
        }

Testando questo codice vi verrà visualizzata una pagina con il trace abilitato.

Il primo numero rosso che vedrete, è il thread di ASP.NET utilizzato all'inizio dell'applicazione.
Come potete vedere dal vostro trace, il thread viene rilasciato immediatamente e, poco sotto, c'è un'altro numero in rosso che identifica l'altro thread di ASP.NET utilizzato nel momento in cui i dati sono disponibili, ovvero una volta dentro il metodo ws1_GetDataCompleted.

Questo renderà la vostra applicazione più scalabile e renderà difficile un errore di tipo 503 – Service Unavailable.

Tags: