ThreadPool.RegisterWaitForSingleObject使用方法

发布时间:2020-07-18 18:14:05 作者:cnn237111
来源:网络 阅读:7057

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

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 方法而不是取决于注册的等待句柄的终结器,则垃圾回收的工作效率更高。

推荐阅读:
  1. strace使用方法
  2. Drivedroid 使用方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

多线程 异步 fo

上一篇:大主子表关联的性能优化方法

下一篇:Java编程思想让很多新手止步不前,困惑已久的问题由此解开

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》