Basta chiedersi l'approccio migliore quando si tratta di asincrono. All'inizio il mio codice sembrava questo (l'esempio è semplificato).. Async Continua con VS Incorporamento delle attività in attività
public NotificationSummary SendNotification()
{
var response = new NotificationSummary();
var first = FindSubscriptions(1);
...
var seventh = FindSubscriptions(7);
Task.WaitAll(first, ... , seventh);
response.First = first.Result;
...
response.Seventh = seventh.Result;
return response;
}
private Task<NotificationResult> FindSubscriptions(int day)
{
return Task.Run(() =>
{
var subscriptions = // call to database to get list of subscriptions
var tasks = subscriptions.Select(x => SendOutNotification(x))
var results = Task.WhenAll(tasks).Result.ToList();
return // map results to NotificationResult
}
}
private Task<IndividualResult> SendOutNotification(Subscription subscription)
{
return Task.Run(() =>
{
var response = new IndividualResult();
foreach(var user in subscription.Users)
{
try
{
// Send user info to EMAIL API
response.Worked.Add(user);
}
catch(Exception ex) { response.Failed.Add(user)}
}
return response;
}
}
Ma questo approccio sta violando singola responsabilità e potrebbe essere fonte di confusione per altri sviluppatori quando vengono provano a capire che cosa questo codice sta facendo. Stavo cercando di trovare un modo per concatenare i compiti e mi sono imbattuto in ContinueWith. Ho fatto qualche ricerca (aka guardato altri post StackOverflow) e ottengo recensioni contrastanti su ContinueWith. Mi piacerebbe davvero che il mio metodo SendNotification assomigliasse a questo, ma non so se questo è un buon approccio quando si tratta di async e tasking.
public NotificationSummary SendNotification()
{
var response = new NotificationSummary();
var firstTasks = new List<IndivdualResult>();
var first = FindSubscriptions(1).ContinueWith(x=>
x.Result.ForEach(r =>
firstTasks.Add(SendOutNotification(x).Result)));
response.First = // map first;
// do 2 - 7 tasks as well
return response;
}
private Task<List<Subscription>> FindSubscriptions() {} //returns subscriptions
private Task<IndividualResults> SendOutNotication() {} // same as above
Mi chiedo quale di questi approcci sarebbe considerato il "modo giusto" se entrambi?
Si sta costantemente bloccando in modo sincrono le attività, il che sta vanificando lo scopo di rendere quelle operazioni asincrone in primo luogo. Se le operazioni non devono essere asincrone, quindi renderle sincrone per iniziare. Se hanno bisogno di essere effettivamente asincroni, non è necessario attendere in modo sincrono che finiscano. – Servy
Perché questo viola l'SRP? – usr
@Servy Capisco cosa intendi. Quindi ho davvero bisogno di dare il via a tutti i compiti e poi avere una funzione di attesa che dopo inizia a scoppiare i risultati. – Beastwood