Come faccio a fare in modo che l'applicazione ASP.NET esegua un'azione in base al tempo?

6

Ho un'applicazione ASP.NET MVC4. Supponiamo che volessi eseguire un codice (come inviare un messaggio via email a un utente) 2 giorni dopo che un utente si è registrato.

Un modo è di avere codice eseguito su ogni richiesta che analizza il database per gli utenti e il loro tempo di registrazione ed esegue il codice in base a ciò. Questo sembra disordinato e dipende dalle persone che visitano l'applicazione frequentemente.

Un altro modo è scrivere un'applicazione separata che gira sul server 24 ore su 24, 7 giorni su 7, esegue il controllo stesso, magari eseguendo la scansione del database ogni giorno alle 12:00 e eseguendo il proprio codice.

Qual è il modo migliore per farlo?

    
posta Rowan Freeman 15.04.2013 - 02:29
fonte

6 risposte

6

Un'attività pianificata attivata dall'Utilità di pianificazione o da Sql Server è la strada da percorrere qui. Ma se vuoi davvero gestirlo all'interno della tua webapp, potresti voler guardare qualcosa come Quartz.NET . Ti consentirà di eseguire attività pianificate dal CLR. Quindi la tua sfida è "come posso assicurarmi che l'AppDomain rimanga attivo per eseguire le attività."

Un altro modo di farlo come operazione programmata mantenendo la maggior parte delle "intelligenze" sul server è di renderlo un'attività che può essere chiamata su HTTP con una sorta di chiave di autorizzazione. Ciò ti consente di scrivere un programma relativamente semplice per chiamarlo - se non un semplice script di shell - e per mantenere la maggior parte della complessità nell'app Web che è probabilmente già in grado di eseguire l'attività.

In ogni caso, rotolare il tuo task manager è davvero un percorso pieno di pericoli.

    
risposta data 15.04.2013 - 15:32
fonte
4

Esistono soluzioni gratuite, facili, professionali e solide come hangfire progettate per fare esattamente questo, con tentativi, registrazione e materiale. Lo consiglio.

(Se ciò è impossibile per qualche motivo: ai vecchi tempi abbiamo appena creato un'applicazione "console" .NET e abbiamo utilizzato Attività pianificate (integrate in Windows) per eseguirlo su una pianificazione (ad esempio una volta ogni ora). Un'altra opzione molto diffusa è stata la creazione del proprio servizio Windows .NET, un po 'più "serio" e probabilmente più robusto, più complicato da configurare e un po' più difficile da eseguire il debug, tuttavia.

    
risposta data 15.04.2013 - 06:57
fonte
3

Un terzo modo consiste nell'impostare un "server delle attività", che potrebbe essere il proprio server o un thread indipendente sul server.

Crea una classe che contiene due membri: un timestamp e un "task", che non è un'attività .NET, ma una rappresentazione di tutte le informazioni che il server dovrà fare qualunque cosa debba essere fatta .

Crea una coda di priorità thread-safe degli oggetti di questa classe, che ordinerà in base al timestamp. Il primo oggetto che esce dalla coda dovrebbe sempre essere quello con il timestamp più basso.

Il thread del server funziona così:

while true
   var time = queue.peek.timestamp
   if time > Now
      sleep(Now - time)
   queue.pop.task.execute
   if queue.empty
      block until there's an item in the queue
end

Questo è il concetto di base. La pianificazione delle attività ripetitive (ogni giorno a mezzanotte esegue X) e la garanzia che le attività pianificate vengano mantenute anche in caso di errore del server vengono lasciate come esercizio per il lettore.

    
risposta data 15.04.2013 - 02:41
fonte
2

L'approccio che utilizziamo è creare un NServiceBus Saga con un timeout .

L'applicazione Web invia un messaggio, la saga viene avviata e richiede un timeout per 2 giorni. Se non si sono verificate altre azioni che potrebbero impedire l'invio dell'e-mail, il timeout riattiva la saga e invia l'e-mail. La richiesta di cancellazione invia anche un messaggio che riattiva la saga e imposta una bandiera annullata.

Questo approccio è ben disaccoppiato dall'applicazione web e facilmente scalabile, inoltre i messaggi vengono accodati in modo da poter arrestare il lato di elaborazione per gli aggiornamenti senza chiudere l'app Web.

L'altra cosa bella di questa architettura è che si basa su eventi piuttosto che su polling, quindi c'è meno conflitto e traffico sul database.

    
risposta data 15.04.2013 - 16:50
fonte
1

Sicuramente NON usare la tua prima idea! lol Questo porterebbe a enormi problemi nel backend quando le cose inizieranno a diventare più grandi.

Se il tuo back-end è MS Sql Server (indovinando i tag nel tuo post), sql server ha la possibilità di pianificare le attività, eliminando la necessità di "eseguire il ping" della tua app per causare l'attività da eseguire (che è molto inaffidabile se cose importanti dipendono da questo). Se questa è un'opzione per te, allora è probabilmente il percorso migliore, a meno che la logica di business dell'app non abbia bisogno di accedere all'attività anche per qualche motivo. Se questo è il caso, le opzioni menzionate in altre risposte andranno bene. Un'altra opzione da tenere presente è che se si eseguono processi pianificati in SQL Server e si hanno diversi lavori che si desidera eseguire in sequenza o in modo asincrono, è possibile associarli a trigger in posizioni appropriate che avviano le attività successive (o parallele).

Una nota sull'idea del task server però: L'idea di un server delle attività andrebbe bene, ma l'idea di creare un thread dedicato sul server potrebbe essere molto inaffidabile a causa del riavvio del pool di app e, cosa più importante, dei timeout dei thread (ad esempio, attività che vengono eseguite una volta al giorno o ogni pochi giorni ). Solo un suggerimento.

    
risposta data 15.04.2013 - 10:05
fonte
1

A partire da ASP.Net 4.0 hai accesso a una funzione Auto-Start per le tue applicazioni ASP.Net, il che significa che puoi avere un thread in esecuzione come un servizio di Windows, ma tenerlo in esecuzione in il contesto della tua applicazione ASP.Net. È un po 'complicato configurare la prima volta che lo si utilizza, ma una volta configurato, è molto utile per mantenere l'intera applicazione in un unico posto.

    
risposta data 15.04.2013 - 15:43
fonte

Leggi altre domande sui tag