创建多个线程并等待所有线程完成

use*_*949 57 .net c#

如何创建多个线程并等待所有线程完成?

Gre*_*som 109

这取决于您使用的.NET Framework版本.使用Tasks,.NET 4.0使线程管理变得更加容易:

class Program
{
    static void Main(string[] args)
    {
        Task task1 = Task.Factory.StartNew(() => doStuff());
        Task task2 = Task.Factory.StartNew(() => doStuff());
        Task task3 = Task.Factory.StartNew(() => doStuff());

        Task.WaitAll(task1, task2, task3);
                Console.WriteLine("All threads complete");
    }

    static void doStuff()
    {
        //do stuff here
    }
}
Run Code Online (Sandbox Code Playgroud)

在以前的.NET版本中,您可以手动使用该BackgroundWorker对象,使用ThreadPool.QueueUserWorkItem()或创建线程并使用Thread.Join()它们等待它们完成:

static void Main(string[] args)
{
    Thread t1 = new Thread(doStuff);
    t1.Start();

    Thread t2 = new Thread(doStuff);
    t2.Start();

    Thread t3 = new Thread(doStuff);
    t3.Start();

    t1.Join();
    t2.Join();
    t3.Join();

    Console.WriteLine("All threads complete");
}
Run Code Online (Sandbox Code Playgroud)

  • Task API是迄今为止最干净的解决方案. (6认同)

Che*_*hen 29

我想你需要WaitHandler.WaitAll.这是一个例子:

public static void Main(string[] args)
{
    int numOfThreads = 10;
    WaitHandle[] waitHandles = new WaitHandle[numOfThreads];

    for (int i = 0; i < numOfThreads; i++)
    {
        var j = i;
        // Or you can use AutoResetEvent/ManualResetEvent
        var handle = new EventWaitHandle(false, EventResetMode.ManualReset);
        var thread = new Thread(() =>
                                {
                                    Thread.Sleep(j * 1000);
                                    Console.WriteLine("Thread{0} exits", j);
                                    handle.Set();
                                });
        waitHandles[j] = handle;
        thread.Start();
    }
    WaitHandle.WaitAll(waitHandles);
    Console.WriteLine("Main thread exits");
    Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

编辑 FCL有一些更方便的功能.

(1)Task.WaitAll及其重载,当你想并行执行某些任务(并且没有返回值)时.

var tasks = new[]
{
    Task.Factory.StartNew(() => DoSomething1()),
    Task.Factory.StartNew(() => DoSomething2()),
    Task.Factory.StartNew(() => DoSomething3())
};    
Task.WaitAll(tasks);
Run Code Online (Sandbox Code Playgroud)

(2)Task.WhenAll当你想用返回值做一些任务时,它执行操作并将结果放在一个数组中.它是线程安全的,您不需要使用线程安全的容器并自己实现添加操作.

var tasks = new[]
{
    Task.Factory.StartNew(() => GetSomething1()),
    Task.Factory.StartNew(() => GetSomething2()),
    Task.Factory.StartNew(() => GetSomething3())
};    
var things = Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)


Vin*_*ent 6

我做了一个非常简单的扩展方法来等待集合的所有线程:

using System.Collections.Generic;
using System.Threading;
namespace Extensions
{
    public static class ThreadExtension
    {
        public static void WaitAll(this IEnumerable<Thread> threads)
        {
            if(threads!=null)
            {
                foreach(Thread thread in threads)
                { thread.Join(); }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你只需致电:

List<Thread> threads=new List<Thread>();
//Add your threads to this collection
threads.WaitAll();
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 5

在.Net 4.0中,您可以使用任务并行库.

在早期版本中,您可以Thread在循环中创建对象列表,调用Start每个对象,然后进行另一个循环并调用Join每个对象.

  • @user:如果你在启动线程后立即调用`Join`,你最终会在启动任何其他线程之前等待它完成.你需要启动_all_的线程,**然后**`Join`全部. (2认同)

小智 5

如果您不想使用Task class(例如,在 .NET 3.5 中),您可以启动所有线程,然后将它们添加到列表中并将它们加入循环中foreach

例子:

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

// Start threads
for (int i = 0; i < 10; i++) {
    int tmp = i; // Copy value for closure
    Thread t = new Thread(() => Console.WriteLine(tmp));
    t.Start();
    threads.Add(t);
}

// Join threads (wait threads)
foreach (Thread thread in threads) {
    thread.Join();
}
Run Code Online (Sandbox Code Playgroud)