控制threadpool執行緒的順序啟動 - WaitHandle.WaitAll 方法

[C#.NET][Thread] 執行緒的順序啟動 - WaitHandle.WaitAll 方法

WaitHandle.WaitAll 跟Thread.Join很像,都是執行緒等待,在功能上就是執行緒的順序啟動,如同我之前寫過的 [Thread] 執行緒的順序啟動 - Thread.Join方法,實作過程很簡單只需要注意以下兩點

1.WaitHandle是一個抽像類別所以我們得實體化它的子類別,也就是 ManualResetEvent 類別 或AutoResetEvent 類別,如下所示

static WaitHandle[] waitHandles = new WaitHandle[]     
{        
    new AutoResetEvent(false),        
    new AutoResetEvent(false)    
};

 

2.再來,看一下多載清單,WaitHandle.WaitAll方法只收WaitHandle[]參數

image

 


接下來則演練如何實作WaitHandle,我用一個類別將我要的資訊擺進去

 

public class Calculator
{
    public string Name { get; set; }
    public long Result { get; set; }

    private AutoResetEvent _WaitHandle;
    public AutoResetEvent WaitHandle
    {
        get { return _WaitHandle; }
        set { _WaitHandle = value; }
    }
}

用戶端的呼叫

 

static WaitHandle[] waitHandles = null;
static object _lock = new object();

static void Main(string[] args)
{
    DateTime dt = DateTime.Now;
    Console.WriteLine("進入主執行緒");
    //建立集合
    List<Calculator> calculator = new List<Calculator>() 
    {
        new Calculator{Result=0,WaitHandle=new AutoResetEvent(false),Name="NO.1"},
        new Calculator{Result=0,WaitHandle=new AutoResetEvent(false),Name="NO.2"}
    };
    //建立WaitHandle陣列,因為WaitHandle.WaitAll只收陣列
    waitHandles = new WaitHandle[calculator.Count];
    for (int i = 0; i < calculator.Count; i++)
    {
        waitHandles[i] = calculator[i].WaitHandle;
    }

    ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), calculator[0]);
    ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), calculator[1]);
    //等待這兩隻執行緒完成工作
    WaitHandle.WaitAll(waitHandles);
    Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds);

    Console.ReadKey();
}

模擬大量運算工作

static void DoTask(Object state)
{
    lock (_lock)
    {
        if (_isTimeOut)
            return;
        Calculator calculator = (Calculator)state;
        Console.WriteLine("{0} 進入子執行緒", calculator.Name);

        AutoResetEvent reset = calculator.WaitHandle;

        for (long i = 0; i < 1000000000; i++)
        {
            calculator.Result++;
        }
        Console.WriteLine("{0} 計算結果 :{1}", calculator.Name, calculator.Result.ToString());
        Console.WriteLine("{0} 離開子執行緒", calculator.Name);
        reset.Set();
    }
} 

執行結果就跟我想的一樣,因為 WaitHandle.WaitAll(waitHandles)的關係,主執行緒乖乖的等待所有執行緒完成工作, 

image


WaitHandle.WaitAll還可以設定等待時間,我們把WaitHandle.WaitAll(waitHandles)改成WaitHandle.WaitAll(waitHandles,2000),表示主執行緒願意等子執行緒2秒。

因為ThreadPool沒有Abort方法所以,我加一個變數_isTimeOut旗標,用來判斷執行緒是否結束工作。

再改裝一下程式碼,

 

static bool _isTimeOut=false; static void Main(string[] args) { …略 //等待這兩隻執行緒完成工作 WaitHandle.WaitAll(waitHandles,2000); _isTimeOut = true; Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds); Console.ReadKey(); } 

static void DoTask(Object state) { lock (_lock) { if (_isTimeOut) return; …略 for (longi = 0; i < 1000000000; i++) { //離開子執行緒旗標 if (_isTimeOut) { Console.WriteLine("{0} 計算結果 :{1}", calculator.Name, calculator.Result.ToString()); Console.WriteLine("{0} 離開子執行緒", calculator.Name); return; } calculator.Result++; } …略 } }

 

執行結果,主執行緒等了2秒後,就不想等了,於是就叫子執行緒停下他的工作。

image


WaitHandle.WaitAny方法就是等待任何一隻執行緒完成工作

static void Main(string[] args)
{
   …略

    //等待任一隻執行緒完成工作
    int index = WaitHandle.WaitAny(waitHandles);
    _isTimeOut = true;

    Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds);

    Console.ReadKey();
}

 

執行結果:可以觀察出當任一執行緒完成工作後則離開所有子執行緒

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值