當我們在使用線程中,你會發現主線結束后子線程的結果才顯示出來。現在我要等待所以子線程結束,然后在顯示結果,怎么做呢?
方法如下:
1、使用 ManualResetEvent,代碼如下:
using System.Threading;
namespace ThreadStudy
{
/// <summary>
/// 等待所有子線程結束
/// </summary>
class StopAllWaitBySubThread
{
List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ManualResetEvent mre = new ManualResetEvent( false);
manualEvents.Add(mre);
ThreadPool.QueueUserWorkItem(ThreadMethod, mre);
}
WaitHandle.WaitAll(manualEvents.ToArray());
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
// 等待2秒,用於模擬系統在處理事情
Thread.Sleep( 2000);
ManualResetEvent mre = (ManualResetEvent)obj;
mre.Set();
Console.WriteLine( " Thread execute ");
}
}
}
namespace ThreadStudy
{
/// <summary>
/// 等待所有子線程結束
/// </summary>
class StopAllWaitBySubThread
{
List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ManualResetEvent mre = new ManualResetEvent( false);
manualEvents.Add(mre);
ThreadPool.QueueUserWorkItem(ThreadMethod, mre);
}
WaitHandle.WaitAll(manualEvents.ToArray());
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
// 等待2秒,用於模擬系統在處理事情
Thread.Sleep( 2000);
ManualResetEvent mre = (ManualResetEvent)obj;
mre.Set();
Console.WriteLine( " Thread execute ");
}
}
}
此種方法線程中只傳遞了信號,那要傳遞參數怎么辦?可以采用類,將信號放在類中來解決,代碼如下。
using System.Threading;
namespace ThreadStudy
{
/// <summary>
/// 等待所有子線程結束
/// </summary>
class StopAllWaitBySubThread
{
List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ManualResetEvent mre = new ManualResetEvent( false);
manualEvents.Add(mre);
Param pra = new Param();
pra.mrEvent = mre;
pra.praData = i;
ThreadPool.QueueUserWorkItem(ThreadMethod, pra);
}
WaitHandle.WaitAll(manualEvents.ToArray());
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
Thread.Sleep( 2000);
Param pra = (Param)obj;
pra.mrEvent.Set();
Console.WriteLine( " Thread execute at {0} ", pra.praData);
}
}
public class Param
{
public ManualResetEvent mrEvent;
public int praData;
}
}
namespace ThreadStudy
{
/// <summary>
/// 等待所有子線程結束
/// </summary>
class StopAllWaitBySubThread
{
List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ManualResetEvent mre = new ManualResetEvent( false);
manualEvents.Add(mre);
Param pra = new Param();
pra.mrEvent = mre;
pra.praData = i;
ThreadPool.QueueUserWorkItem(ThreadMethod, pra);
}
WaitHandle.WaitAll(manualEvents.ToArray());
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
Thread.Sleep( 2000);
Param pra = (Param)obj;
pra.mrEvent.Set();
Console.WriteLine( " Thread execute at {0} ", pra.praData);
}
}
public class Param
{
public ManualResetEvent mrEvent;
public int praData;
}
}
2、判斷線程數
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadStudy
{
/// <summary>
/// 判斷當所有子線程執行完畢
/// </summary>
class ThreadPoolStop
{
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem( new WaitCallback(ThreadMethod), i);
}
int maxWorkerThreads, workerThreads;
int portThreads;
while ( true)
{
/*
GetAvailableThreads():檢索由 GetMaxThreads 返回的線程池線程的最大數目和當前活動數目之間的差值。
而GetMaxThreads 檢索可以同時處於活動狀態的線程池請求的數目。
通過最大數目減可用數目就可以得到當前活動線程的數目,如果為零,那就說明沒有活動線程,說明所有線程運行完畢。
*/
ThreadPool.GetMaxThreads( out maxWorkerThreads, out portThreads);
ThreadPool.GetAvailableThreads( out workerThreads, out portThreads);
if (maxWorkerThreads - workerThreads == 0)
{
Console.WriteLine( " Thread Finished! ");
break;
}
}
}
private void ThreadMethod( object i)
{
Console.WriteLine( " Thread execute at {0} ", i.ToString());
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadStudy
{
/// <summary>
/// 判斷當所有子線程執行完畢
/// </summary>
class ThreadPoolStop
{
public void Main()
{
for ( int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem( new WaitCallback(ThreadMethod), i);
}
int maxWorkerThreads, workerThreads;
int portThreads;
while ( true)
{
/*
GetAvailableThreads():檢索由 GetMaxThreads 返回的線程池線程的最大數目和當前活動數目之間的差值。
而GetMaxThreads 檢索可以同時處於活動狀態的線程池請求的數目。
通過最大數目減可用數目就可以得到當前活動線程的數目,如果為零,那就說明沒有活動線程,說明所有線程運行完畢。
*/
ThreadPool.GetMaxThreads( out maxWorkerThreads, out portThreads);
ThreadPool.GetAvailableThreads( out workerThreads, out portThreads);
if (maxWorkerThreads - workerThreads == 0)
{
Console.WriteLine( " Thread Finished! ");
break;
}
}
}
private void ThreadMethod( object i)
{
//模擬程序運行
Thread.Sleep((
new Random().Next(
1,
4)) *
1000);
Console.WriteLine( " Thread execute at {0} ", i.ToString());
}
}
}
3、使用Monitor
using System.Threading;
namespace ThreadStudy
{
class StopAllSubThread
{
int _ThreadCount = 5;
int finishcount = 0;
object locker = new object();
public void Main()
{
for ( int i = 0; i < _ThreadCount; i++)
{
Thread trd = new Thread( new ParameterizedThreadStart(ThreadMethod));
trd.Start(i);
}
lock (locker)
{
while (finishcount != _ThreadCount)
{
Monitor.Wait(locker); // 等待
}
}
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
// 模擬執行程序
Thread.Sleep( 3000);
Console.WriteLine( " Thread execute at {0} ", obj.ToString());
lock (locker)
{
finishcount++;
Monitor.Pulse(locker); // 完成,通知等待隊列,告知已完,執行下一個。
}
}
}
}
namespace ThreadStudy
{
class StopAllSubThread
{
int _ThreadCount = 5;
int finishcount = 0;
object locker = new object();
public void Main()
{
for ( int i = 0; i < _ThreadCount; i++)
{
Thread trd = new Thread( new ParameterizedThreadStart(ThreadMethod));
trd.Start(i);
}
lock (locker)
{
while (finishcount != _ThreadCount)
{
Monitor.Wait(locker); // 等待
}
}
Console.WriteLine( " Thread Finished! ");
}
private void ThreadMethod( object obj)
{
// 模擬執行程序
Thread.Sleep( 3000);
Console.WriteLine( " Thread execute at {0} ", obj.ToString());
lock (locker)
{
finishcount++;
Monitor.Pulse(locker); // 完成,通知等待隊列,告知已完,執行下一個。
}
}
}
}