C#, how do I know when all my theads have finished?
我有一个"线程"类,它会抛出执行进程的线程。 线程在threader类中有一个回调方法,当它们完成时会被调用。 我的问题是我怎么知道穿线器抛出的所有线程都结束了?
如果您对已启动的线程数进行计数,则可以在线程启动时简单地增加计数,而在线程完成时则简单地减少计数。
然后,当计数为零时,您就知道所有线程都已完成。
在处理寿命短的线程时,您需要注意确保计数器允许在递减之前递增。需要使用某种锁定或
您可以为活动线程数保留一个简单的计数器。或者,您可以让线程在开始工作之前在集合中注册(添加)自己,并在完成时将其删除。
计数是可行的,但可能比您想象的要难实现...请确保在线程内的
如果仅创建一些线程并拥有线程实例,则也可以使用Thread.Join每个实例。即使线程在调用join之前终止了(但仍在实例被清除之前),该方法仍然有效。
所以:
1 2 3 4 | foreach( Thread thread in myThreads) { thread.join(); } |
一旦完成,您确定所有线程都已完成。
hth
马里奥
线程计数器的示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | long counter = 0; void ThreadEntryPoint() { try { ... // } finally { // Decrement counter Interlocked.Decrement(ref counter); } } void MainThread() { // Start worers for(...) { // Increment threads couter Interlocked.Increment(ref counter); ((Action)ThreadEntryPoint).BeginInvoke(null, null); } // Wait until counter is equal to 0 while(Interlocked.Read(ref counter) != 0) { Thread.Sleep(0); } } |
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | static class ThreadingExtensions { // Possible: // [ThreadStatic] // private static List<WaitHandle> PerThreadWaitList; public const int MaxHandlesPerWait = 64; public static void WaitAll< T >(this IEnumerable< T > handles, int millisecondsTimeout, int estimatedCount) where T : WaitHandle { // Possible: // var currentSet = PerThreadWaitList ?? (PerThreadWaitList = new List<WaitHandle>(estimatedCount)); var currentSet = new List<WaitHandle>(Math.Min(estimatedCount, MaxHandlesPerWait)); var timeoutEnd = Environment.TickCount + millisecondsTimeout; int timeout; // Wait for items in groups of 64. foreach (var item in handles) { currentSet.Add(item); if (currentSet.Count == MaxHandlesPerWait) { timeout = Timeout.Infinite; if (millisecondsTimeout >= 0) { timeout = timeoutEnd - Environment.TickCount; if (timeout < 0) throw new TimeoutException(); } WaitHandle.WaitAll(currentSet.ToArray(), timeout); currentSet.Clear(); } } // Do the last set. if (currentSet.Count > 0) { timeout = Timeout.Infinite; if (millisecondsTimeout >= 0) { timeout = timeoutEnd - Environment.TickCount; if (timeout < 0) timeout = 0; } WaitHandle.WaitAll(currentSet.ToArray(), timeout); currentSet.Clear(); } } } |
并举例说明。
1 2 3 4 | var results = new List<IAsyncResult>(); // Call delegates, e.g. // results.Add(Foo.BeginInvoke(OnEndInvokeFoo)); results.Select(x => x.AsyncWaitHandle).WaitAll(Timeout.Infinite, results.Count); |
在穿线器线程中检查每个线程的状态。如果所有线程都已停止(或中止),则可以结束主线程。
最简单的方法是,如果您事先知道将要运行的线程数,则可以在回调函数中使用计数器。
如果您不知道线程数,那么您需要一些"处理结束"指示符来设置布尔值以及已创建和结束线程的计数器。
如果您不知道将要创建的线程数,那么一个简单的两个计数器的想法将行不通(如果第一个线程在创建任何其他线程之前开始并结束,那么它将错误地认为这是最后一个线程)之一)。