2015-09-24 236 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並等待

這應該清理混亂並解決效率問題。

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