首先我們看一下它的原型:
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, 5000, false);
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, 5000, false);
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, 5000, false);
Console.ReadKey();
}
private static void test11( object state, bool timedOut)
{
Console.WriteLine( " aaa ");
}
}
}
因為ManualResetEvent會一值保持開關量為true,所以會一直觸發執行回調函數。
