2015-09-24 87 views
6

只是想知道最好的方法,当谈到异步。起初我的代码看起来像这样(例子被简化了)。.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。我做了一些研究(又名其他的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 

我想知道这些方法中的一个将被认为是“正确的方式”如果任?

+1

你总是在同步阻塞任务,这首先破坏了使这些操作异步的目的。如果操作不需要是异步的,那么使它们同步开始。如果他们需要实际上是异步的,那么你不需要同步等待他们完成。 – Servy

+0

为什么这违反了SRP? – usr

+0

@Servy我明白你的意思。所以我真的需要开始所有的任务,然后有一个waitall函数,在开始分析结果之后。 – Beastwood

回答

5

ContinueWith是代码气味,因为await成为可用。 await基本上是附加延续的好方法。

我看不出第一版代码的结构性问题。你应该:

  • 替换所有Wait/Result电话与await
  • 删除Task.Run用途
  • 用的await代替了WaitAll WhenAll
  • 一个新的异步方法代替ContinueWith并等待

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

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