.Net Async ContinueWith VS 在任务中嵌入任务
.Net Async ContinueWith VS Embedding Tasks in Task
只是想知道异步的最佳方法。起初我的代码看起来像这样(示例已简化)。
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。我做了一些研究(也就是查看了其他 Whosebug 帖子),我对 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
我想知道这些方法中的哪一种会被认为是 "right way" 如果有的话?
ContinueWith
是自 await
可用以来的代码味道。 await
基本上是附加延续的好方法。
我发现您的代码的第一个版本没有结构问题。你可能应该:
- 将所有
Wait/Result
调用替换为 await
- 删除 Task.Run 用法
- 将 WaitAll 替换为 await WhenAll
- 用新的异步方法替换 ContinueWith 并等待
这应该可以清理混乱并解决效率问题。
如果你不需要并行,你也可以让一切同步。
只是想知道异步的最佳方法。起初我的代码看起来像这样(示例已简化)。
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。我做了一些研究(也就是查看了其他 Whosebug 帖子),我对 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
我想知道这些方法中的哪一种会被认为是 "right way" 如果有的话?
ContinueWith
是自 await
可用以来的代码味道。 await
基本上是附加延续的好方法。
我发现您的代码的第一个版本没有结构问题。你可能应该:
- 将所有
Wait/Result
调用替换为await
- 删除 Task.Run 用法
- 将 WaitAll 替换为 await WhenAll
- 用新的异步方法替换 ContinueWith 并等待
这应该可以清理混乱并解决效率问题。
如果你不需要并行,你也可以让一切同步。