51 messaggi dal 16 gennaio 2009
Buongiorno,rieccomi con un'altra domanda da principiante.
ho implementato nell'applicazione ASP.NET core un hosted service, cioè un task in background dove gira la logica applicativa e fino a qui tutto bene.
Però non ho chiaro qual'è il meccanismo per lo scambio dati tra i due mondi.
Ad esempio: premendo un bottone su una pagina scateno la relativa action, quindi presumo che dovrei scrivere qualcosa nella suddetta action che mi permetta di scatenare, ad esempio, un evento nel task in background. Però non ho capito come.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
ho un'applicazione di esempio su GitHub che risponde alla tua domanda:
https://github.com/BrightSoul/background-email-sender
L'applicazione in questione serve ad inviare email da un hosted service, ma anche la situazione che hai descritto tu è realizzabile nello stesso modo. Se non l'hai già letto, questo script è propedeutico.


Ad esempio: premendo un bottone su una pagina scateno la relativa action, quindi presumo che dovrei scrivere qualcosa nella suddetta action che mi permetta di scatenare, ad esempio, un evento nel task in background

Ecco l'action in questione che invoca il metodo Post del servizio IEmailSender.
https://github.com/BrightSoul/background-email-sender/blob/master/Controllers/HomeController.cs#L27

L'invocazione a quel metodo Post serve ad accodare del lavoro per l'hosted service, come vedi qui, nella classe che implementa l'interfaccia IEmailSender.
https://github.com/BrightSoul/background-email-sender/blob/master/HostedServices/EmailSenderHostedService.cs#L84

L'accodamento avviene tramite la classe BufferBlock<T> che è thread-safe e serve a realizzare scenari producer-consumer come questo (il producer è l'action che accoda lavoro, mentre il consumer è l'hosted service che scoda lavoro e lo esegue). Nel tuo caso magari vorrai anche persistere il lavoro nel database, in modo che non vada perso se l'applicazione dovesse arrestarsi.

Se ci fai caso, la classe che implementa IEmailSender è proprio l'hosted service stesso, che è stato configurato sia come hosted service che come servizio singleton. Nota la particolare configurazione che permette di riusare la stessa istanza in entrambi i casi.
https://github.com/BrightSoul/background-email-sender/blob/master/Startup.cs#L28

Lunga vita e prosperità,
Moreno
Modificato da BrightSoul il 21 marzo 2019 19:34 -

Enjoy learning and just keep making
51 messaggi dal 16 gennaio 2009
Grazie a te Moreno comincio a capirci qualcosa.
Adesso l'ostacolo è capire bene come sistemare i models e, di conseguenza, le view.
Ho dei metodi della mia business logic, fatti in precedenza, che mi ritornano dei datatable e portarli su dei datagrid ASP non mi sembra una operazione proprio banale. Ma come sempre sono difficili solo le cose che non si conoscono...

Ciao e grazie per il supporto
51 messaggi dal 16 gennaio 2009
Riesumo questa discussione perchè non ho le idee ancora molto chiare.
Nel tuo esempio Moreno ritorni alla pagina una risposta di email inviata usando (se non ho capito male)un tipo ILogger che restituisce un messaggio.
Ma se devo restituire un dato complesso (nel mio caso specifico una lista di stringhe, ma potrebbe essere anche un datatable) come si può fare?
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


Nel tuo esempio Moreno ritorni alla pagina una risposta di email inviata usando (se non ho capito male)un tipo ILogger che restituisce un messaggio.

No, in questo caso l'ILogger non c'entra. E' un servizio di ASP.NET Core usato per loggare delle righe di testo arbitrarie e viene usato solo al momento dell'effettivo invio della mail, giusto per tenere traccia del fatto che l'invio si è verificato. Non è un servizio essenziale ai fini dell'esempio.


ritorni alla pagina una risposta di email inviata

Sì... questo avviene in questa riga di codice, quando reindirizzo alla view ThankYou che poi mostra il messaggio.

In realtà, la view ThankYou NON dice "L'email è stata inviata", perché non sarebbe vero.
La view dice: "We reiceved your message and we're going to get in touch with you soon!"

Il messaggio dell'utente è stato solo accodato, perché l'effettivo invio per email si verificherà in un secondo momento, in background, ad opera dell'hosted service. L'accodamento si verifica in questa riga di codice, che internamente usa un BufferBlock gestire la coda, come vedi in questa riga di codice.

Quando la richiesta dell'utente si è conclusa, non c'è garanzia che l'email sia stata già inviata. Verrà inviata con tutta calma dall'hosted service, in questa riga di codice, in maniera del tutto indipendente dalla richiesta dell'utente.

Tu avevi appunto chiesto che il Task (in questo caso l'invio di un'email) si verificasse in background.

Premendo un bottone su una pagina scateno la relativa action, quindi presumo che dovrei scrivere qualcosa nella suddetta action che mi permetta di scatenare, ad esempio, un evento nel task in background

Confermi che è questo il caso?

Detto questo... ho bisogno di chiarimenti a proposito della tua domanda.

Ma se devo restituire un dato complesso (nel mio caso specifico una lista di stringhe, ma potrebbe essere anche un datatable)

La lista di stringhe o il DataTable sono ottenute da questo Task che viene elaborato in background? Se sì, dato che il lavoro viene eseguito in background, ormai la richiesta dell'utente è bella che conclusa. Puoi usare due approcci:
  • Se il task in background richiede svariati secondi (o anche minuti), puoi inviare il risultato (es. lista di stringhe) usando SignalR. Cioè: è il server che fa push del risultato verso il client.
  • Oppure, se il task in background richiede pochissimi secondi (Es. 3 secondi), puoi anche fare a meno dell'hosted service e recuperare la lista di stringhe dal database grazie a un servizio applicativo e poi restituirla al client tramite view di MVC o tramite dati json di WebAPI.


Comunque, scrivimi un messaggio in privato che ti mando una cosa.

ciao,
Moreno
Modificato da BrightSoul il 26 aprile 2019 11:49 -

Enjoy learning and just keep making
51 messaggi dal 16 gennaio 2009

La lista di stringhe o il DataTable sono ottenute da questo Task che viene elaborato in background? Se sì, dato che il lavoro viene eseguito in background, ormai la richiesta dell'utente è bella che conclusa. Puoi usare due approcci:

Se il task in background richiede svariati secondi (o anche minuti), puoi inviare il risultato (es. lista di stringhe) usando SignalR. Cioè: è il server che fa push del risultato verso il client.
Oppure, se il task in background richiede pochissimi secondi (Es. 3 secondi), puoi anche fare a meno dell'hosted service e recuperare la lista di stringhe dal database grazie a un servizio applicativo e poi restituirla al client tramite view di MVC o tramite dati json di WebAPI.


Buongiorno Moreno

In realtà ho due casi distinti:

- L'utente richiede dei dati alle macchine connesse tramite comando (il famoso pulsante). La risposta è veloce, diciamo nell'ordine di qualche decina di millisecondi, e viene processato da una apposita richiesta in background per mezzo di metodi sincroni, cioè che attendono la risposta.
I dati di ritorno fino ad ora li ho formattati in un DataTable per ragioni di praticità poichè, nell'applicativo WinForm attualmente sviluppato, vengono visualizzati in DataGridView e vorrei mantenere la stessa operatività. In realtà non provengono da un database ma vengono forniti in apposite strutture da appositi metodi di DLL fornite dai vari costruttori di macchine.

- La logica di background fa un polling sulle macchine perchè dovrei anche rendere visibili alcuni stati delle macchine stesse, in questo caso penso che l'uso di signalR sia adatto. Alcune pagine ASP, quando richiamate dovrebbero in altre parole monitorare ciclicamente l'impianto.
In realtà ci sono anche eventi che vengono scatenati nel task di background, quindi non gestiti dal polling ma dall'arrivo di dati sui socket di connessione con l'impianto, che vengono utilizzati nella business logic e che dovrei rendere disponibili all'utente a livello informativo. Ma anche in questo caso penso che l'utilizzo di signalR vada bene.

Come avrai capito, l'applicazione a livello di business logic funziona già e l'ho ben chiara nella mia mente. I miei ostacoli sono dovuti alla mia inesperienza nel campo delle applicazioni Web per quanto riguarda lo scambio dati tra l'applicazione stessa e le pagine ASP.

Ti ho mandato come richiesto un messaggio privato e ti ringrazio ancora per la tua disponibilità.

Ciao
11.886 messaggi dal 09 febbraio 2002
Contributi

L'utente richiede dei dati alle macchine connesse tramite comando (il famoso pulsante). La risposta è veloce, diciamo nell'ordine di qualche decina di millisecondi, e viene processato da una apposita richiesta in background per mezzo di metodi sincroni, cioè che attendono la risposta.

Ok, non ho ben capito che intendi con "richiesta in background". Si tratta di una richiesta ajax che parte dopo che la pagina è stata caricata? Se sì, va bene così come hai fatto.


La logica di background fa un polling sulle macchine perchè dovrei anche rendere visibili alcuni stati delle macchine stesse, in questo caso penso che l'uso di signalR sia adatto.

Certo. Ogni volta che i dati sono disponibili, li mandi ai client connessi per mezzo di SignalR.


In realtà ci sono anche eventi che vengono scatenati nel task di background. Ma anche in questo caso penso che l'utilizzo di signalR vada bene.

Sì, puoi usare SignalR anche in questo caso.


I miei ostacoli sono dovuti alla mia inesperienza nel campo delle applicazioni Web per quanto riguarda lo scambio dati tra l'applicazione stessa e le pagine ASP.

Ok, scendiamo un po' più nel particolare e vediamo un po' di codice. Cosa hai realizzato finora e dove ti blocchi esattamente?

Il progetto che ti ho linkato ti è stato d'aiuto?
Ti linko anche quest'altro esempio, simile al precedente, ma che forse è più vicino al tuo scenario. Anche qui c'è un hosted service che ogni secondo genera un'immagine, a simulare il tuo polling. L'immagine viene poi inviata ai client tramite SignalR. Questo esempio serve a dimostrare come si inviano dati binari (l'immagine) ma lo stesso principio lo puoi usare anche per dati strutturati. Nel readme del progetto trovi anche la spiegazione di come è costruito.
https://github.com/BrightSoul/aspnetcore-realtime-binary
Se hai bisogno di chiarimenti sono qua.

ciao,
Moreno

Enjoy learning and just keep making
51 messaggi dal 16 gennaio 2009

Ok, non ho ben capito che intendi con "richiesta in background". Si tratta di una richiesta ajax che parte dopo che la pagina è stata caricata? Se sì, va bene così come hai fatto.

Mi sono espresso male. Intendevo dire che la parte di "business logic", che gira in background in un task separato ciclico, si preoccupa di gestire la lettura dei dati in polling dalle macchine (diciamo, per usare un termine forse improprio: non sollecitati) ma implementa anche i metodi per andare a leggere o scrivere dati su richiesta.
Per farti un esempio: in una apposita pagina ASP l'utente deve poter richiedere i dati degli utensili (parliamo di centri di lavoro) della macchina X, che non serve vengano letti ciclicamente.
La velocità di risposta è comunque variabile e dipendente dalla mole di dati richiesta. Può andare da poche decine di msec a 2-3 sec poichè dipende anche dal tipo di automazione che vado ad interrogare.
Comunque adesso mi studio il nuovo esempio che mi hai linkato ed il videocorso.
Grazie ancora.

Ciao

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.