2012-07-26 80 views
3
class MultiThreading 
{ 
    public class ThreadClass 
    { 
     public string InputString { get; private set; } 
     public int StartPos { get; private set; } 
     public List<SearchAlgorithm.CandidateStr> completeModels; 
     public List<SearchAlgorithm.CandidateStr> partialModels; 

     public ThreadClass(string s, int sPos) 
     { 
      InputString = s; 
      StartPos = sPos; 
      completeModels = new List<SearchAlgorithm.CandidateStr>(); 
      partialModels = new List<SearchAlgorithm.CandidateStr>(); 
     } 

     public void Run(int strandID) 
     { 
      Thread t = new Thread(() => this._run(strandID)); 
      t.Start(); 
     } 

     private void _run(int strandID) 
     { 
      SearchAlgorithm.SearchInOneDirection(strandID, ref this.completeModels, ref this.partialModels); 
     } 

     public static void CombineResult(
      List<ThreadClass> tc, 
      out List<SearchAlgorithm.CandidateStr> combinedCompleteModels, 
      out List<SearchAlgorithm.CandidateStr> combinedPartialModels) 
     { 
      // combine the result 
     } 
    } 
} 

class Program 
    { 

     static void Main(string s, int strandID) 
     { 
      int lenCutoff = 10000; 
      if (s.Length > lenCutoff) 
      { 
       var threads = new List<MultiThreading.ThreadClass>(); 
       for (int i = 0; i <= s.Length; i += lenCutoff) 
       { 
        threads.Add(new MultiThreading.ThreadClass(s.Substring(i, lenCutoff), i)); 
        threads[threads.Count - 1].Run(strandID); 
       } 


       **// How can I wait till all thread in threads list to finish?** 
      } 
     } 
    } 

我的問題是我該如何等待「線程」列表中的所有線程完成,然後再調用CombineResult方法?多線程中的等待問題

感謝

+1

如果您在使用C#4.0中,你有沒有使用[任務並行庫(HTTP考慮:// msdn.microsoft.com/en-us/library/dd460717.aspx)?非常喜歡直接編寫自己的線程。 – 2012-07-26 16:31:43

+0

您可能最好閱讀[Task Class](http://msdn.microsoft.com/zh-cn/library/dd235678),它內置了'WaitAll'方法。 – nicholas 2012-07-26 16:31:59

+0

可能重複[如何等待線程完成與.NET?](http://stackoverflow.com/questions/1584062/how-to-wait-for-thread-to-finish-with-net) – 2012-07-26 16:33:42

回答

1

ThreadClass暴露的手段join the thread

private Thread nativeThread; 
    public void Run(int strandID) 
    { 
     nativeThread = new Thread(() => this._run(strandID)); 
     nativeThread.Start(); 
    } 

    public void Join() 
    { 
     nativeThread.Join(); 
    } 

然後用ThreadClass.Join每個線程在啓動之後他們:

var threads = new List<ThreadClass>(); 
    for (int i = 0; i <= s.Length; i += lenCutoff) 
    { 
     threads.Add(new ThreadClass(s.Substring(i, lenCutoff), i)); 
     threads[threads.Count - 1].Run(strandID); 
    } 

    // Waits for each thread to finish in succession 
    threads.ForEach(t => t.Join()); 

或者,扔掉你的ThreadClass和享受System.Threading.Tasks

// e.g. class Models { Complete; Partial; } 
// private Models Search(string source, int offset, int length, int ID) 
var tasks = new List<Task<Models>>(
    from x in Enumerable.Range(0, s.Length/lenCutoff) 
    select Task.Factory.StartNew<Models>(
     () => Search(s, x, lenCutoff, strandID)); 
); 

// private Models CombineResults(IEnumerable<Models> results) 
var combine = Task.Factory.ContinueWhenAll<Models>(
    tasks.ToArray(), 
    ts => CombineResults(ts.Select(t => t.Result))); 

combine.Wait(); 

Models combinedModels = combine.Result; 
5

您可以添加List<Thread>結構,以保持所有線程的記錄

private List<Thread> threads = new List<Thread>(); 

然後填充線程

public void Run(int strandID) 
{ 
    Thread t = new Thread(() => this._run(strandID)); 
    t.Start(); 
    threads.Add(t); 
} 

最後的名單,你可以有用於調用Join的方法列表中的每個線程。它通常是一個很好的做法,有一個超時延遲,所以你的程序永遠不會阻塞(如果有主題中的錯誤)

public void WaitAll(List<Thread> threads, int maxWaitingTime) 
{ 
    foreach (var thread in threads) 
    { 
     thread.Join(maxWaitingTime); //throws after timeout expires 
    } 
} 


另一種方法是使用一個 Task類和調用 Task.WaitAll

+0

而不是在使用它的類中實現WaitAll函數,而是在IEnumerable上實現它作爲擴展方法 2012-07-26 16:33:49

+0

WaitAll方法是否會中斷並行計算? – Mavershang 2012-07-26 17:44:26

+0

@Mavershang不會的。如果在'maxWaitingTime'時間內計算還沒有結束,那麼'WaitAll'的調用將會簡單地返回。同時你的線程將進行計算。如果您需要中斷計算,則需要允許[取消](http://msdn.microsoft.com/zh-cn/library/dd997396.aspx)。使用原生的'Thread'真的很難。並且不要調用'Thread.Abort'谷歌爲什麼。 – oleksii 2012-07-26 18:57:10

1

那麼我看到答案已經被選中,但我已經開始使用System.Threading.Tasks編寫一個解決方案,如其他幾個人所建議的。而不是使用LINQ,我試圖原代碼的結構儘可能匹配:

class SearchClass 
{ 
    public String InputString { get; private set; } 
    public int StartPos { get; private set; } 
    public List<string> completeModels; 
    public List<string> partialModels; 

    public SearchClass(string s, int sPos) 
    { 
     InputString = s; 
     StartPos = sPos; 
     completeModels = new List<string>(); 
     partialModels = new List<string>(); 
    } 

    public void Run(int strandID) 
    { 
     // SearchAlgorithm.SearchInOneDirection(...); 
    } 

    // public static void CombineResult(...){ }; 
} 

class Program 
{ 
    static void Main(string s, int strandID) 
    {  
     int lenCutoff = 10000; 

     if (s.Length > lenCutoff) 
     { 
      var searches = new List<SearchClass>(); 
      var tasks = new List<System.Threading.Tasks.Task>(); 

      for (int i = 0; i < s.Length; i += lenCutoff) 
      { 
       SearchClass newSearch = new SearchClass(s.Substring(i, lenCutoff), i); 
       searches.Add(newSearch); 
       tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(()=>newSearch.Run(strandID))); 
      } 

      System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); 

      // Combine the result 
     } 
    } 
}