. net Async ContinueWith VS在Task中嵌入任务

本文关键字:任务 Task Async ContinueWith VS net | 更新日期: 2023-09-27 18:14:27

只是想知道异步的最佳方法。首先,我的代码看起来像这样(示例是简化的):

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。我做了一些研究(也就是看了其他stackoverflow的帖子),我在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

我想知道这些方法中的哪一种会被认为是"正确的方法",如果有的话?

. net Async ContinueWith VS在Task中嵌入任务

ContinueWith是自await可用以来的代码气味。await基本上是一种附加延续的好方法。

我看不出你第一个版本的代码有什么结构问题。你可能应该:

  • await
  • 替换所有Wait/Result调用
  • 删除任务。运行使用
  • 将WaitAll替换为await WhenAll
  • 用新的异步方法替换ContinueWith并等待

这应该清理混乱和解决效率问题。

如果你不需要并行性,你也可以使一切都是同步的。