非同期の場合に最適なアプローチが不思議です。最初は私のコードはこのように見えました(例は単純化されています)。.Net Async ContinueWith VSタスクに埋め込みタスクを含める
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;
}
}
しかし、このアプローチは、単一の責任に違反していると、彼らは、このコードが何をしているかを把握しようとしてくるときに、それは他の開発者に混乱するかもしれません。私は仕事をつなぎ合わせる方法を見つけようとしていました。私はContinueWithに出くわしました。私はいくつかの研究を行いました(別のスタックオーバーフロー記事を見ました)、私はContinueWithに関する複数のレビューを受け取ります。私は実際にSendNotificationメソッドをこのようにしたいと思いますが、これが非同期とタスクになると良いアプローチであるかどうかはわかりません。
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
これらのアプローチのどちらが「正しい方法」と考えられるのでしょうか?
あなたは常にタスクを同期的にブロックしています。これは、最初にそれらの操作を非同期にする目的を打ち負かしています。操作が非同期である必要がない場合は、それらを同期させて開始してください。実際に非同期にする必要がある場合は、同期が完了するまで待つ必要はありません。 – Servy
これはなぜSRPに違反していますか? – usr
@サービーあなたは何を意味するのか分かります。だから、私は本当にすべてのタスクを開始し、その後、結果を打ち始めるwaitall機能を持っている必要があります。 – Beastwood