C# 如何等待所有后台线程完成(在C中)?

C# 如何等待所有后台线程完成(在C中)?,c#,multithreading,C#,Multithreading,如何使前台线程等待所有后台(子)线程在C#中完成?我需要从队列(数据库)中获取挂起作业的列表,启动一个新线程来执行每个作业,最后等待所有子线程完成。在C#中如何做到这一点?提前感谢。您可以将每个启动的线程存储在一个数组中。然后,当您需要等待所有线程时,对循环中数组中的每个线程调用Join方法 Thread child = new Thread(...); Threads.Add(child); child.Start() ... foreach(Thread t in Threads) {

如何使前台线程等待所有后台(子)线程在C#中完成?我需要从队列(数据库)中获取挂起作业的列表,启动一个新线程来执行每个作业,最后等待所有子线程完成。在C#中如何做到这一点?提前感谢。

您可以将每个启动的线程存储在一个数组中。然后,当您需要等待所有线程时,对循环中数组中的每个线程调用Join方法

Thread child = new Thread(...);
Threads.Add(child);
child.Start()

...

foreach(Thread t in Threads)
{
   t.Join();
}

HTH

这是一个不完整的代码,但
ManualResetEvent
适用于您

var waitEvents = new List<ManualResetEvent>();
foreach (var action in actions)
{
    var evt = new ManualResetEvent(false);
    waitEvents.Add(evt);
    ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, TimeoutCallback, state, 5000, true);
}

if (waitEvents.Count > 0)
    WaitHandle.WaitAll(waitEvents.ToArray());
var waitEvents=new List();
foreach(行动中的var行动)
{
var evt=新手动重置事件(错误);
waitEvents.Add(evt);
RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle,TimeoutCallback,state,5000,true);
}
如果(waitEvents.Count>0)
WaitHandle.WaitAll(waitEvents.ToArray());

创建一个结构来跟踪工作线程

private struct WorkerThreadElement
{
    public IAsyncResult WorkerThreadResult;
    public AsyncActionExecution WorkerThread;
}
您还需要跟踪预期要创建的线程总数和当前已完成的线程数

private int _TotalThreads = 0;
private int _ThreadsHandled = 0;
private List<WorkerThreadElement> _WorkerThreadElements = new List<WorkerThreadElement>();
您还需要一个委托来创建新线程——有多种方法可以做到这一点,但是为了这个示例,我选择了一个简单的委托

// Delegate to asynchronously invoke an action
private delegate void AsyncActionExecution();
让我们假设Invoke方法是将创建所有线程并等待其执行的入口点。因此,我们:

public void Invoke()
{ 
    _TotalThreads = N; /* Change with the total number of threads expected */

    foreach (Object o in objects) 
    {
        this.InvokeOneThread();
    }             

    // Wait until execution has been completed
    _CompletedHandle.WaitOne();

    // Collect any exceptions thrown and bubble them up
    foreach (WorkerThreadElement workerThreadElement in _WorkerThreadElements)
    {
        workerThreadElement.WorkerThread.EndInvoke(workerThreadElement.WorkerThreadResult);
    }
}         
InvokeOneThread是用于为一个操作创建单个线程的方法。这里我们需要创建一个worker-thread元素并调用实际的线程

 private void InvokeOneThread()
 {
     WorkerThreadElement threadElement = new WorkerThreadElement();
     threadElement.WorkerThread = new AsyncActionExecution();
     threadElement.WorkerThreadResult = threadElement.WorkerThread.BeginInvoke(actionParameters, InvokationCompleted, null);

     _WorkerThreadElements.Add(threadElement);
 }
线程完成回调

private object _RowLocker = new object();

/// <summary>
/// Increment the number of rows that have been fully processed
/// </summary>
/// <param name="ar"></param>
private void InvokationCompleted(IAsyncResult ar)
{
    lock (_RowLocker) 
    {
        _RowsHandled++; 
    }

    if (_TotalThreads == _ThreadsHandled) 
        _CompletedHandle.Set();
}
private object_RowLocker=new object();
/// 
///增加已完全处理的行数
/// 
/// 
私有void InvokationCompleted(IAsyncResult ar)
{
锁(_RowLocker)
{
_RowsHandled++;
}
如果(_TotalThreads==_threadshanded)
_CompletedHandle.Set();
}

完成

考虑使用线程池。你想要的大部分已经完成了。这是一个可以完成你全部任务的程序。将“fibonacci”替换为“database task”,这听起来像是您的问题。

使用动态数据,您可以传递对象和WaitHandle(ActionResetEvent),它允许您在不声明额外类的情况下等待所有后台线程完成:

static void Main(string[] args)
{
    List<AutoResetEvent> areList = new List<AutoResetEvent>();
    foreach (MyObject o in ListOfMyObjects)
    {
        AutoResetEvent are = new AutoResetEvent(false);
        areList.Add(are);
        ThreadPool.QueueUserWorkItem(DoWork, new { o, are });
    };

    Console.WriteLine("Time: {0}", DateTime.Now);
    WaitHandle.WaitAll(areList.ToArray());
    Console.WriteLine("Time: {0}", DateTime.Now);
    Console.ReadKey();
}

static void DoWork(object state)
{
    dynamic o = state;
    MyObject myObject = (MyObject)o.o;
    AutoResetEvent are = (AutoResetEvent)o.are;

    myObject.Execute();
    are.Set();
}
static void Main(字符串[]args)
{
List areList=新列表();
foreach(MyObject列表中的MyObject o)
{
AutoResetEvent are=新的AutoResetEvent(假);
areList.Add(are);
QueueUserWorkItem(DoWork,new{o,are});
};
WriteLine(“时间:{0}”,DateTime.Now);
WaitHandle.WaitAll(areList.ToArray());
WriteLine(“时间:{0}”,DateTime.Now);
Console.ReadKey();
}
静态无效工作(对象状态)
{
动态o=状态;
MyObject MyObject=(MyObject)o.o;
自动还原事件are=(自动还原事件)o.are;
myObject.Execute();
are.Set();
}

have u try的可能重复感谢您对我的问题的快速回复谢谢您的回复。我认为thread.Join方法适用于单个线程或极少数固定数量的线程。对于多线程,我认为有一个WaitAll方法,但我找不到一个好的代码示例。@RKP:等待所有线程完成与依次等待它们是一样的,不是吗?有一个winapi函数WaitForMultipleObjects,但它不是C#,虽然您可以使用它,但我看不出有什么意义。谢谢,但是在这段代码中,每个操作的新线程是从哪里开始的?“5000”是一个超时设置吗?看看这里的整个代码,我只是从我以前的一个答案中复制了一点:是的,5000是一个超时设置我几分钟前读了这篇文章,正要回复说这就是我要寻找的解决方案。谢谢你的回复。
static void Main(string[] args)
{
    List<AutoResetEvent> areList = new List<AutoResetEvent>();
    foreach (MyObject o in ListOfMyObjects)
    {
        AutoResetEvent are = new AutoResetEvent(false);
        areList.Add(are);
        ThreadPool.QueueUserWorkItem(DoWork, new { o, are });
    };

    Console.WriteLine("Time: {0}", DateTime.Now);
    WaitHandle.WaitAll(areList.ToArray());
    Console.WriteLine("Time: {0}", DateTime.Now);
    Console.ReadKey();
}

static void DoWork(object state)
{
    dynamic o = state;
    MyObject myObject = (MyObject)o.o;
    AutoResetEvent are = (AutoResetEvent)o.are;

    myObject.Execute();
    are.Set();
}