ThreadPool.RegisterWaitForSingleObject使用方法

其实很早之前用过这个方法,只是很久没用,又生疏了。记录下来作为备忘。

成都创新互联是网站建设专家,致力于互联网品牌建设与网络营销,专业领域包括网站设计制作、成都做网站、电商网站制作开发、小程序开发、微信营销、系统平台开发,与其他网站设计及系统开发公司不同,我们的整合解决方案结合了恒基网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,且不断评估并优化我们的方案,为客户提供全方位的互联网品牌整合方案!

ThreadPool.RegisterWaitForSingleObject和ThreadPool.QueueUserWorkItem都是ThreadPool类中的静态方法。

ThreadPool.RegisterWaitForSingleObject 有4个重载函数,都大同小异。

这里只演示一种方法的使用

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

MSDN中的说明是:

注册一个等待 WaitHandle 的委托,并指定一个 32 位有符号整数来表示超时值(以毫秒为单位)。

说的比较模糊。我用自己的语言来叙述一下。

ThreadPool.RegisterWaitForSingleObject中必须传入一个WaitHandle,这个WaitHandle一旦接受到信号,或者没接收信号而超时了,则会调用WaitOrTimerCallback方法。这个超时时间由millisecondsTimeOutInterval设置的。如果超时时间设为-1,那么只要接受不到信号,那么一直WaitOrTimerCallback则一直不会运行。该方法不会阻塞线程,只是在线程池上开启一个线程来处理回调。

executeOnlyOnce的值为true/false。如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。

注意,WaitOrTimerCallback 委托 签名如下:

[ComVisibleAttribute(true)]
public delegate void WaitOrTimerCallback(
Object state,
bool timedOut
)

这个委托运行的时候,Object state参数就是RegisterWaitForSingleObject方法中传入的Object state,timedOut参数就是等待是否超时,如果RegisterWaitForSingleObject方法中的超时时间是10s,那么在10s后,WaitHandle还未收到信号,则为true,反之则反。

下面演示一段代码。

static void Main(string[] args)
{
	Console.WriteLine(DateTime.Now.ToLongTimeString() + " Main Thread start " + " threadID: " + Thread.CurrentThread.GetHashCode());
	AutoResetEvent are = new AutoResetEvent(false);
	RegisteredWaitHandle waithandle = ThreadPool.RegisterWaitForSingleObject(are, (o, t) =>
	{
		string s = (string)o;
		Console.WriteLine(DateTime.Now.ToLongTimeString() + " callback dosomething " + " threadID:" + Thread.CurrentThread.GetHashCode());
		Console.WriteLine(DateTime.Now.ToLongTimeString() + " TimeOut:" + t.ToString());
	}, "state", 2 * 1000, true);
	Console.WriteLine(DateTime.Now.ToLongTimeString() + " Main Thread did someting ");
	are.Set();
	Thread.Sleep(2000);
	Console.WriteLine(DateTime.Now.ToLongTimeString() + " end");
}

运行结果如下:

ThreadPool.RegisterWaitForSingleObject使用方法

RegisterWaitForSingleObject中的WaitOrTimerCallback方法是一个拉姆达表达式,超时时间为2秒。运行后可以看到主线程ID是1,WaitOrTimerCallback的线程ID是4,也证明了这个回调是在其他线程(线程池线程)中做的。 代码中Thread.Sleep(2000);如果不加入的话,可能主线程运行完毕,回调方法还未来得及运行。TimeOut为False。

如果在are.Set();  前面加上一句等待Thread.Sleep(3000);那么TimeOut为True,因为等3秒再给出信号已经超时了。

如果把RegisterWaitForSingleObject中的参数executeOnlyOnce设为false,那么方法中的回调会重复执行。(把主线程中的 Thread.Sleep改为5000;)得到的结果如下:

ThreadPool.RegisterWaitForSingleObject使用方法

可以看到,回调首次不超时,而接下来在主线程结束之前,会有2次超时导致的调用。因此,这个方法也可用作计时器。微软的文档中,建议:

此方法返回的 RegisteredWaitHandle 使用完毕后,请调用其 RegisteredWaitHandle.Unregister 方法来释放对等待句柄的引用。 我们建议始终调用 RegisteredWaitHandle.Unregister 方法,即使将 executeOnlyOnce 指定为 true 也是如此。 如果调用 RegisteredWaitHandle.Unregister 方法而不是取决于注册的等待句柄的终结器,则垃圾回收的工作效率更高。


名称栏目:ThreadPool.RegisterWaitForSingleObject使用方法
分享链接:http://csdahua.cn/article/jdjsoj.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流