2012-07-26 55 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 
     } 
    } 
}