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