2015-04-17 10 views
3

我需要啓動不是並行的「數量」任務(變量但少於10),並且等待它們全部完成,從每個結果。 我得到他們每個人的結果,保存在列表中,然後最終使用它。並行運行多個任務(變量編號),並在所有完成時繼續運行

這是我的代碼,它正在工作,但我認爲那裏應該有一個更乾淨的方法。

任務對引起

List<String> Arguments = new List<String> { "AA", "BB", "CC" }; 

List<String> ResultList = new List<String>(); 

//**AT LEAST I'VE GOT ONE** 

Task<String> Tasks = Task<String>.Factory.StartNew(() => 
{ 
    return DoSomething(Arguments[0]); 
}); 

ResultList.Add(Tasks.Result); 

for (Int32 i = 1; i < Arguments.Count; i++) 
{ 
    ResultList.Add(Tasks.ContinueWith<String>(Result => 
    { 
     return DoSomething(Arguments[i]); 

    }).Result); 
} 

//**DO I NEED THIS?? It's working even without!!** 
//Tasks.Wait(); 

for (Int32 i = 0; i < ResultList.Count; i++) 
{ 
    textBox1.AppendText(ResultList[i] + Environment.NewLine + Environment.NewLine); 
} 
+3

爲什麼你需要多個任務?爲什麼你需要一個任務,當你所做的只是**同步**等待它完成。 – Alex

+0

你可以使用async await – Orifjon

+0

'Tasks.Result'不會編譯。 –

回答

1

的數量,您不需要Wait()電話。文檔Task<T>.Result陳述如下:

訪問屬性的get訪問器會阻止調用線程,直到異步操作完成;它相當於調用Wait方法。

0

可以使用異步等待

public async List<String> SomeMethod() { 
    List<String> Arguments = new List<String> { "AA", "BB", "CC" }; 
    List<String> ResultList = new List<String>(); 
    foreach(var argument in Arguments) 
    { 
    var result = await DoSomething(argument); 
    ResultList.Add(result); 
    } 
    return ResultList; 
} 
2

我認爲這是你正在嘗試做的:即啓動的並行任務的整個負載,並等待他們都在進行

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace UnitTestProject2 
{ 
    class Class4 
    { 
     public void run() 
     { 
      List<String> Arguments = new List<String> { "AA", "BB", "CC" }; 
      List<Task<String>> tasks = new List<Task<string>>(); 

      foreach (string arg in Arguments) 
      { 
        tasks.Add(
         this.DoSomething(arg) 
         .ContinueWith(t => this.DoSomething(t.Result)) 
         .Unwrap<string>() 
        ); 
      } 

      Task.WaitAll(tasks.ToArray()); 

      foreach(Task<string> t in tasks) 
      { 
       textBox1 += (t.Result + Environment.NewLine + Environment.NewLine); 
      } 

     } 

     public async Task<string> DoSomething(string arg) 
     { 
      return arg; 
     } 

     public string textBox1; 
    } 
} 
前完成
+0

如果它對你有效,請接受答案 – Ewan

+0

'.Result'可以引發'AggregateException' – VMAtm

+0

你的意思是在lambda?我必須承認,我通常會繼續使用方法並傳遞任務,以便您可以處理未完成任務,但msdn有結果lambda的例子,並且對於示例更加簡潔。也意味着你可以使用兩次相同的方法 – Ewan

0

到目前爲止,您的整個代碼都是同步運行的。您正在創建一個Task,然後主動阻止它,使用Task.Result

如果你真正瞭解是什麼並行,並且你確實需要,你有參數要在列表中執行儘可能多的任務,那麼你可以卸載所有的人,然後異步等待(這是關鍵,是異步),因爲它們完成:

var arguments = new[] { "A", "B", "C" }; 
var tasks = arguments.Select(argument => Task.Run(() => DoSomething(argument))).ToList(); 

while (tasks.Count > 0) 
{ 
    var finishedTask = await Task.WhenAny(tasks); 
    textBox1.AppendText(string.Format("{0}{1}{1}", finishedTask.Result, 
                Environment.NewLine)); 

    tasks.Remove(finishedTask); 
} 

編輯: 從您的評論:

我打電話的web API(不是我的),不允許我在多個並行調用 ,這就是爲什麼我需要等待每個任務完成

那麼你並不需要爲每個線程根本沒有論據。兩件事:

  1. 您可以使呼叫完全同步,因爲您必須等待每個呼叫的完成。使用線程池線程僅僅是無用的
  2. 您可以進行異步調用,而不需要使用線程。看看HttpClient及其XXXAsync方法(如GetAsync)。
+0

是的,謝謝。 – AngelBlueSky

相關問題