66 messaggi dal 03 ottobre 2009
Salve a tutti,
sto lavorando ad un progetto in contesto WebForm e volevo sapere se qualcuno sa darmi indicazioni su come "bloccare e rilevare l'elaborazione di un metodo", cerco di spiegarmi meglio.
Semplificando al massimo ho un metodo che esegue la cache dei dati prelevandoli dal database, supponendo che questo metodo impiega diversi minuti ad elaborare la richiesta, dovrei fare in modo di far partire l'elaborazione alla prima chiamata e alle successive chiamate rilevare tale elaborazione fino a che non è stata compiuta.

Faccio un esempio dove due utenti chiamano lo stesso metodo da due browser differenti:

1- utente01 chiama il metodo GetData()
2- il metodo GetData() inizia con l'elaborazione bloccando la risorsa
3- utente01 chiude il browser
4- utente02 chiama il metodo GetData() e viene rilevato che è in fase di elaborazione

Il primo problema da affrontare è come evitare di far interrompere il processo che sta elaborando i dati alla chiusura del browser, questo lo risolvo utilizzando pagine con metodi Async, se ci sono altre modalità accetto suggerimenti.
Successivamente dovrei fare in modo di marcare in qualche modo il metodo che è in fase di elaborazione fino al suo completamento, in modo da poter rilevare tale elaborazione e inviare all'utente l'avviso di attesa, quali strumenti posso utilizzare?

Grazie

Andrea Restucci - Web Developer
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Andrea,


questo lo risolvo utilizzando pagine con metodi Async,

Mmmh, no, lo scopo dei metodi Async è quello di ottimizzare il riutilizzo dei thread quando la tua applicazione fa uso di risorse di I/O, come consumare un webservice o accedere al db.
Potresti usare dei Task, ma leggi prima le considerazioni in questo post di Scott Hanselman.
http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

Quello che ti consiglio personalmente è di non programmare questa cosa a mano, ma di usare una soluzione già pronta come HangFire, di cui tra l'altro Hanselman parla anche nel suo post.

Grazie ad HangFire, un cosiddetto "job" (cioè il metodo di una classe) può andare in esecuzione fuori dal contesto di una richiesta web, e perciò restare in esecuzione indipendentemente dagli utenti connessi all'applicazione. Ti permette anche di schedulare questo "job" e mandarlo in esecuzione, ad esempio, ogni 5 minuti, ammesso che l'esecuzione precedente sia terminata.

Qualche settimana fa abbiamo affrontato un problema simile al tuo in questa discussione.
http://forum.aspitalia.com/forum/post/412306/DataSet.ReadXml-Valori-Consentiti.aspx?pageIndex=6
Scaricati il progetto di esempio, che usa HangFire per mandare in esecuzione il job e SignalR per fare rapporto sul suo progresso in realtime ai vari client connessi (non sarà necessario aggiornare la pagina).

SignalR è una bell'aggiunta ma non è fondamentale, perché HangFire ha una API di monitoraggio che ti consente di sapere se un dato job è attualmente in esecuzione oppure no. Vedi questo articolo nella documentazione:
http://docs.hangfire.io/en/latest/background-processing/tracking-progress.html

ciao,
Moreno

Enjoy learning and just keep making
66 messaggi dal 03 ottobre 2009
grazie mille
mi leggo un pò di documentazione e ti faccio sapere

Ciao

Andrea Restucci - Web Developer
66 messaggi dal 03 ottobre 2009
Grazie Moreno,
ho risolto con HangFire, l'ho implementato senza l'utilizzo di SignalR, tanto per il mio utilizzo va già più che bene.

A questo punto vorrei un altro consiglio in merito visto che mi sembri molto preparato in materia, parliamo di cache.
La mia web-app, sviluppata in Aspnet Webform, fa utilizzo massiccio di dati memorizzati in cache come liste di oggetti, praticamente faccio un pre-caricamento di tutte le tabelle in cache e lavoro totalmente "disconnesso".
Per il momento utilizzo la cache fornita da .net System.Web.Caching, vorrei però utilizzare uno strumento più adatto in modo che posso controllare meglio l'operatività, in tal senso pensavo di approcciare ad AppFabric, cosa ne pensi?
Hai altro da consigliare?

Grazie

Andrea Restucci - Web Developer
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Andrea,


faccio un pre-caricamento di tutte le tabelle in cache e lavoro totalmente "disconnesso".

Ok, fammi sapere perché hai scelto questa soluzione. Per darti un consiglio devo sapere quali vantaggi hai ottenuto o quali problemi hai dovuto evitare.

Enjoy learning and just keep making
66 messaggi dal 03 ottobre 2009
ok grazie,
allora diciamo che è stata una scelta un pò "sbagliata" a seguito di una scarsa conoscenza degli strumenti già presenti in commercio.
Senza andare per le lunghe praticamente mi sono auto-costruito un semplice ORM quando invece avrei potuto utilizzare uno prodotto già completo (EF - Nhibernate), prossimamente penserò ad una conversione.
Attualmente mi ritrovo dunque con oggetti (da me definiti) che mappano le varie tabelle-viste e un piccolo tool (sempre da me sviluppato) che recupera i dati da db e crea liste di oggetti che verranno caricati in memoria (cache) per poi essere consumati con LINQ-to-object.
Ovviamente il tool da me progettato in caso di operazioni CRUD su db non andrà a rigenerare l'intera cache ma solo il record corrispondente.
Devo dire che malgrado tutto il consumo della memoria non è eccessivo e la velocità di interrogazione dati è ottima.
Punto critico è il pre-caricamento dei dati che non è così istantaneo e ovviamente la gestione del codice.
Il vantaggio invece è quello di avere piena padronanza sul codice che gestisce il data-layer.
In merito a ciò ti chiedo:
come funzionano gli ORM presenti in commercio?
quando fai qualche interrogazione eseguono il read ogni volta da db o hanno i dati in memoria?
Tornando invece al mio progetto ecco che dunque vorrei implementare uno strumento per gestire al meglio la cache, attualmente uso System.web.caching

Andrea Restucci - Web Developer
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Andrea,


come funzionano gli ORM presenti in commercio?
quando fai qualche interrogazione eseguono il read ogni volta da db o hanno i dati in memoria?

Si, gli ORM tipicamente inviano una nuova query al database anche se l'utente dovesse richiedere nuovamente gli stessi dati (es. fa F5 per aggiornare la pagina).
Esistono progetti come questo che ti consentono di configurare una cache di secondo livello, ovvero di conservare dei risultati in memoria affinché le successive richieste di pagina siano più veloci.

Attenzione perché questo approccio è un po' diverso dal tuo: in questo caso la query viene usata come "chiave" per accedere ad un set di risultati già pronto da restituire al client.
Nel tuo caso, invece, stai usando Linq to Objects per filtrare un'intera lista di risultati. Anche se è "veloce", non è propriamente efficiente perché una query Linq to Objects è costretta a scorrersi l'intero elenco ogni volta. Capisci che se i tuoi oggetti crescono di numero diventerà sempre meno efficiente scalabile come soluzione.
Un database, invece, è in grado di sfruttare indici per arrivare all'informazione desiderata in maniera molto più efficiente. Il divario nelle prestazioni, rispetto all'usare una cache in memoria, si assottiglierà se inizi ad usare dischi SSD oppure la modalità "memory optimized" di Sql Server 2014, di cui puoi leggere qui:
http://robtiffany.com/create-in-memory-database-tables-sql-server-2014/
Valuta se fa al caso tuo.

Solitamente, se l'obiettivo è abbassare al massimo i tempi di risposta, si scelgono altre soluzioni, come usare la Cache di Output di ASP.NET, creare una versione denormalizzata del database per ogni vista della tua applicazione (per evitare Join) o delegare la ricerca a motori appositi come ElasticSearch. Ne abbiamo parlato qui, insieme ad un altro utente che aveva una situazione simile alla tua. La parte "interessante" si trova a pagina 2.http://forum.aspitalia.com/forum/post/413555/Salvataggio-Dati-Temporanei.aspx?PageIndex=1
Si tratta comunque di soluzioni che dovresti valutare per qualche centinaio o migliaio di utenti contemporanei connessi all'applicazione. Per numeri inferiori sarebbe meno apprezzabile l'apporto fornito da una cache o da un motore di ricerca dedicato (ponendo che le tue query al db siano ottimizzate).

ciao,
Moreno
Modificato da BrightSoul il 08 settembre 2016 19.25 -

Enjoy learning and just keep making
66 messaggi dal 03 ottobre 2009
ok grazie dei suggerimenti, a questo punto vorrei sapere se potrei adottare un ORM con il minimo impatto possibile sul codice, nel senso che le pagine di ricerca sono sviluppate in modo da utilizzare LINQ to object su liste di oggetti quindi ho codice LINQ to object un pò ovunque per non parlare poi di tutte le classi definite che rispecchiano in modo personalizzato le tabelle.
Secondo te mi tocca modificare anche tutte queste porzioni di codice se dovessi adottare un ORM come EF o Nhibernate ?

Andrea Restucci - Web Developer

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.