在多线程中等待问题

时间:2012-07-26 16:23:50

标签: c# multithreading

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方法?

由于

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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;

答案 2 :(得分: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
        }
    }
}