Sto lavorando a un progetto di API Web che utilizza il servizio di cache gestita di Azure per memorizzare nella cache i risultati del database in memoria per migliorare i tempi di risposta e alleviare il traffico duplicato nel database. Quando si tenta di inserire un nuovo elemento nella cache, occasionalmente verrà generata un'eccezione specifica della cache con un codice di DataCacheErrorCode.RetryLater
. Naturalmente, per riprovare più tardi senza dover bloccare questo metodo, l'ho reso async
e await Task.Delay
per riprovare a breve. Precedentemente uno sviluppatore aveva codificato in codice un Thread.Sleep
in quello che stava davvero danneggiando le prestazioni delle applicazioni.Considerazioni per non attendere un'attività in un metodo asincrono
La firma di metodo sembra qualcosa di simile a questo ora:
public static async Task Put(string cacheKey, object obj)
A seguito di questo cambiamento ho ~ 75 avvisi del compilatore da tutti gli altri posti nel applicazione che ha chiamato la versione precedentemente sincrona di Put
indicando:
Poiché questa chiamata non è attesa, l'esecuzione del metodo corrente continua prima che la chiamata sia completata. Prendi in considerazione l'applicazione dell'operatore "Attendi" al risultato della chiamata.
In questo caso, dal momento che Put
non restituisce nulla, ha senso per me di lasciare che questa operazione fire-and-forget come io non vedo alcun motivo per bloccare l'esecuzione del metodo che ha chiamato esso. Mi stavo solo chiedendo se ci sono pericoli o insidie per aver permesso che molti di questi fire-and-forget Task
s in esecuzione in background come Put
possano essere chiamati abbastanza spesso. O dovrei comunque aspettare dal momento che il 99% delle volte non otterrò l'errore e il Task
terminerà quasi immediatamente. Voglio solo assicurarmi di non incorrere in alcuna penalità per avere troppi thread (o qualcosa del genere).
Grazie per il buon feedback. Attualmente tutte le eccezioni diverse da RetryLater vengono catturate e registrate correttamente e siamo su .NET 4.5 quindi sono fiducioso nel lasciare che queste attività si attivino e si dimentichino. –
Tecnicamente Timer utilizza un thread [separato] da un pool di thread, quindi Task.Delay() – alexm
@alexm Utilizza un thread pool di thread per un periodo di tempo molto breve trascorso il tempo necessario per eseguire il gestore. Non consuma un thread thread thread durante l'attesa. Ciò significa che un thread viene sempre utilizzato solo quando ha un lavoro produttivo da fare, che è esattamente quello che vuoi (e non può evitare). – Servy