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

谢谢

4

3 回答 3

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

于 2012-07-26T16:30:08.543 回答
1

ThreadClass公开加入线程的方法:

    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;
于 2012-07-26T16:29:51.367 回答
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
        }
    }
}
于 2012-07-26T19:16:01.893 回答