Contesto: devo lanciare un'operazione che può durare molto tempo eseguita da un metodo sincrono che non torna eventi (legacy). Devo fornire un feedback all'utente (una sorta di pagina clessidra) e, a lavoro terminato, mostrare il risultato.
Soluzione adottata: creo una pagina per iniziare l'operazione e configurarne i parametri (pagina Start), una autorefreshante per comunicare che il
lavoro è in corso (pagina Wait) e una pagina per mostrare i risultati (pagina Results).
La pagina Start:
- mette in sessione un flag per indicare che il calcolo è in corso
- istanzia un delegate per richiamare il metodo sincrono con un nuovo thread;
- lancia il nuovo thread passando eventuali parametri del metodo, un riferimento al metodo di callback e un riferimento al caller stesso
- carica la pagina Wait
Il caller del MetodoLungo:
- a lavoro completato richiama il metodo di callback sulla pagina Start
Il metodo di callback (su Start):
- riaggancia il chiamante
- recupera il risultato del calcolo usando EndInvoke sul chiamante
- mette il risultato in sessione
- setta il flag in sessione per indicare che il calcolo è terminato
La pagina Wait:
- ha un tag meta (magari inserito da codice) per fare il refresh automatico
- verifica il flag in sessione per sapere quando passare alla pagina dei risultati
La pagina Results:
- recupera il risultato dalla sessione e lo mostra

Codice:
pagina Start:
   public delegate TipoRisultatoCalcoloLungo MetodoLungoAsyncCaller(TipoParametro1MetodoLungo par1,   TipoParametro2MetodoLungo par2);

    public partial class StartPage
    {
     ...
     void Toolbar1_ButtonClick(object sender, ToolbarEventArgs ea)
        {
             
Session[SessionConstants.SCAN_IN_PROGRESS] = true;

                        // Create the delegate.
                        MetodoLungoAsyncCaller caller = new MetodoLungoAsyncCaller(MetodoLungo);

                        // Initiate the asychronous call.  Include an AsyncCallback
                        // delegate representing the callback method, and the data
                        // needed to call EndInvoke.
                        IAsyncResult result = caller.BeginInvoke(valorePar1, valorePar2,
                            new AsyncCallback(CallbackMethod),
                            caller);

                        // goto to "hourglass" page
                        Response.Redirect(WebFormsConstants.WAIT_ASPX);
        }
        ...
        // Callback method
        public void CallbackMethod(IAsyncResult ar)
        {
            // Retrieve the delegate.
            MetodoLungoAsyncCaller caller = (MetodoLungoAsyncCaller)ar.AsyncState;

            // Call EndInvoke to retrieve the results.
            TipoRisultatoCalcoloLungo risultato = caller.EndInvoke(ar);
            Session[SessionConstants.RISULTATO] = risultato;
            // set flag in session to comunicate scan completed
            Session[SessionConstants.SCAN_IN_PROGRESS] = false;
         }
         ...
}

pagina Wait:
protected void Page_Load(object sender, EventArgs e)
        {
            HtmlMeta meta = new HtmlMeta();
            meta.HttpEquiv = "refresh";
            meta.Content = "10";
            Header.Controls.Add(meta);

            if ((Boolean)Session[SessionConstants.SCAN_IN_PROGRESS] == false)
                Response.Redirect(WebFormsConstants.RESULT_ASPX);

            Message1.Text = "In Progress";
        }

 

posted on venerdì 30 maggio 2008 3.45
Filed Under [ Scoperte di un principiante ]

Comments

Gravatar
# re: Thread asincrono e pagine asp.net
posted by Andrea Colaci
on 30/05/2008 19.58
Ciao,

dai anche un occhiata a RegisterAsyncTask

http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerasynctask.aspx

supporta anche la gestione del timeout, oltre ai delegates per lo Start End del task asincrono.

Gravatar
# re: Thread asincrono e pagine asp.net
posted by Angella Andrea
on 31/05/2008 7.52
Forse sto per dire una stupidaggine, ma questo sembra un contesto ideale per utilizzare ajax. Puoi avviare una richiesta asincrona lato client, mostrare nell'attesa un feedback all'utente e quando saranno disponibili i risultati aggiornare la pagina o fare un redirect lato client. Sbaglio ?
Gravatar
# re: Thread asincrono e pagine asp.net
on 31/05/2008 9.09
x Andrea Colaci:
grazie Andrea, mi chiedevo proprio come riuscire a gestire un timeout; se il capo progetto mi concede il tempo di farlo lo provo sicuramente.

x Andrea Angella: purtroppo conosco poco ajax. Riesco a immaginare l'avvio della richiesta asincrona lato client; quello che non saprei come fare è la verifica dei risultati perchè il metodo che richiamo (che non può essere modificato) non fornisce alcun feedback se non il valore di ritorno. La mia impressione è che con ajax perderei il riferimento al metodo lanciato e avrei bisogno di un metodo aggiuntivo che verifichi se il lavoro è terminato, ma purtroppo nessuno può saperlo (non posso fare in modo che il metodo lanciato "scriva" da qualche parte il risultato). Secondo te c'è qualche modo per riuscire a farlo? Grazie.
Gravatar
# re: Thread asincrono e pagine asp.net
posted by Angella Andrea
on 01/06/2008 11.13
Con ajax viene fatta una richiesta asincrona al server. Nel momento in cui il risultato dell'elaborazione sarà disponibile (cioè l'output generato dal server) sul client verrà invocato il metodo javascript di callback attraverso il quale sai che l'operazione sul server è terminata (con o senza errore) e puoi utilizzare i risultati come desideri. Visto che tanto devi semplicemente visualizzare una clessidra, o una scritta di attesa (e non gestire una progress bar) tutto il tempo tra l'invocazione della richiesta asincrona e l'arrivo dei risultati sarà in effetti il tempo di elaborazione sul server. Ma quanto dura questa operazione, parliamo di una decina di secondi ?
Gravatar
# re: Thread asincrono e pagine asp.net
posted by Angella Andrea
on 01/06/2008 11.15
Con ajax viene fatta una richiesta asincrona al server. Nel momento in cui il risultato dell'elaborazione sarà disponibile (cioè l'output generato dal server) sul client verrà invocato il metodo javascript di callback attraverso il quale sai che l'operazione sul server è terminata (con o senza errore) e puoi utilizzare i risultati come desideri. Visto che tanto devi semplicemente visualizzare una clessidra, o una scritta di attesa (e non gestire una progress bar) tutto il tempo tra l'invocazione della richiesta asincrona e l'arrivo dei risultati sarà in effetti il tempo di elaborazione sul server. Ma quanto dura questa operazione, parliamo di una decina di secondi ?
Gravatar
# re: Thread asincrono e pagine asp.net
on 01/06/2008 20.16
L'operazione purtroppo può durare anche diversi minuti (si tratta di un metodo eseguito da un componente COM che si interfaccia con una rete di strumenti hardware, che possono essere anche diverse decine). Per ora non gestiamo feedback parziali, ma in futuro dovremo farlo. Comunque stando così le cose posso provare anche ajax, così evito il continuo ricaricamento dell'intera pagina "clessidra".
Gravatar
# re: Thread asincrono e pagine asp.net
posted by Angella Andrea
on 02/06/2008 8.16
Si ed eventualmente puoi utilizzare un timer lato client che esegue una richiesta per sapere se l'operazione è completata, utilizzando il meccanismo delle sessioni. In futuro potrai restituire un valore che indica lo stato dell'operazione e aggiornare (senza refresh) lo stato della pagina. Ciao buon lavoro :-)
Your Comment




 
Please add 3 and 3 and type the answer here: