ThreadPool基礎之RegisterWaitForSingleObject


首先我們看一下它的原型:

 


public  static RegisteredWaitHandle RegisterWaitForSingleObject(
     WaitHandle waitObject,
     WaitOrTimerCallback callBack,
     Object state,
     int millisecondsTimeOutInterval,
     bool executeOnlyOnce
)

 

參數

waitObject

要注冊的 WaitHandle。使用 WaitHandle 而非 Mutex

callBack

waitObject 參數終止時調用的 WaitOrTimerCallback 委托。

state

傳遞給委托的對象。

timeout

TimeSpan 表示的超時時間。如果 timeout 為零,則函數測試對象的狀態並立即返回。如果 timeout 為 -1,則函數的超時間隔永遠不過期。

executeOnlyOnce

如果為 true,表示在調用了委托后,線程將不再在 waitObject 參數上等待;如果為 false,表示每次完成等待操作后都重置計時器,直到注銷等待。

 

 

返回值

封裝本機句柄的 RegisteredWaitHandle

相信看了這些之后大家還是一頭霧水,這個方法的做用是向線程池添加一個可以定時執行的方法,第四個參數millisecondsTimeOutInterval 就是用來設置間隔執行的時間,但是這里第五個參數executeOnlyOnce 會對第四個參數起作用,當它為true時,表示任務僅會執行一次,就是說它不會,像Timer一樣,每隔一定時間執行一次,這個功能的話用Timer控件也可以實現

該方法還在此基礎上提供了基於信號量來觸發執行任務。

信號量也叫開關量,故名思議,它只有兩種狀態,不是true就是false,

WaitHandle就是這類開關量的基礎類,繼承它的類有Mutex,ManualResetEvent,AutoResetEvent,一般我們使用后兩個

寫法:


        static ManualResetEvent wait2=new ManualResetEvent(false);
        static AutoResetEvent wait=new AutoResetEvent(false);

 

我們可以在將其實例化時指定開關量的初始值。(true為有信號,false為沒信號)

ManualResetEvent和AutoResetEvent的區別在於:

前者調用Set方法后將自動將開關量值將一直保持為true,后者調用Set方法將變為true隨后立即變為false,可以將它理解為一個脈沖。

我們來看幾個例子

例子一:實現一個普通的定時器


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace test
{
     class Class14
     {
         static AutoResetEvent wait= new AutoResetEvent( false);
         static  void Main( string[] args)
         {
             object state= new  object();
             ThreadPool.RegisterWaitForSingleObject(wait,  new WaitOrTimerCallback(test11), state, 5000false);
             Console.ReadKey();
         }

         private  static  void test11( object state,  bool timedOut)
         {
                 Console.WriteLine( " aaa ");
         }
     }
}

 

例子二,使用開關量提前執行下一次任務執行的時間為立即執行(有點繞,就是說原先間隔10s執行下一次任務,但是使用了開關量的set方法,立即執行下一次的任務,執行的時間提前了,下一次執行的時間又重新開始算

在這里請注意一個細節,下面的代碼中當我們向線程池中注冊任務的語句即            ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(test11), state,5000, false);
它是間隔5秒執行,當剛加入線程池后它是需要過了5秒后才會第一次執行回調函數的,也就是說不是一加入第0秒就會執行一次回調函數的。這里使用了一個 wait.Set()方法使得立即執行了回調函數而不需要等待5秒鍾,所以輸出結果的第一個“aaa”是由wait.Set()操作引起的。

如果我們不使用wait.Set(),而是將AutoResetEvent wait=new AutoResetEvent(true)的初始值改為true也會在第0秒輸出“aaa”

 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace test
{
     class Class14
     {
         static ManualResetEvent wait2= new ManualResetEvent( false);
         static AutoResetEvent wait= new AutoResetEvent( false);
         static  void Main( string[] args)
         {
             object state= new  object();
             ThreadPool.RegisterWaitForSingleObject(wait,  new WaitOrTimerCallback(test11), state, 5000false);
             wait.Set();
             Console.ReadKey();
         }

         private  static  void test11( object state,  bool timedOut)
         {
                 Console.WriteLine( " aaa ");
         }
     }
}

第三個例子:使用ManualResetEvent,這個例子有點意思,它會不停的輸出"aaa",為什么?

 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace test
{
     class Class14
     {
         static ManualResetEvent wait= new ManualResetEvent( true);
         static  void Main( string[] args)
         {
             object state= new  object();
             ThreadPool.RegisterWaitForSingleObject(wait,  new WaitOrTimerCallback(test11), state, 5000false);

             Console.ReadKey();
         }

         private  static  void test11( object state,  bool timedOut)
         {
                 Console.WriteLine( " aaa ");
         }
     }
}

因為ManualResetEvent會一值保持開關量為true,所以會一直觸發執行回調函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM