本节书摘来自华章出版社《C#多线程编程实战(原书第2版)》一书中的第3章,第3.6节,作者(美)易格恩·阿格佛温(Eugene Agafonov),黄博文 黄辉兰 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3.6 在线程池中使用等待事件处理器及超时
本节将描述如何在线程池中对操作实现超时,以及如何在线程池中正确地等待。
3.6.1 准备工作
为了学习本节,你需要安装Visual Studio 2015。除此之外无需其他准备。本节的源代码放置在BookSamplesChapter3Recipe5目录中。
3.6.2 实现方式
请执行以下步骤来了解在线程池中实现超时及正确的等待:
1.启动Visual Studio 2015。新建一个C#控制台应用程序项目。
2.在Program.cs文件中加入以下using指令:
3.在Main方法下面加入以下代码片段:
4.在Main方法中加入以下代码片段:
5.运行程序。
3.6.3 工作原理
线程池还有一个有用的方法:ThreadPool.RegisterWaitForSingleObject。该方法允许我们将回调函数放入线程池中的队列中。当提供的等待事件处理器收到信号或发生超时时,该回调函数将被调用。这允许我们为线程池中的操作实现超时功能。
首先注册了处理超时的异步操作。有两种情况会触发该异步操作。第一种情况是接收到了ManualRestEvent对象的信号,当工作者操作成功完成后会发出该信号。第二种情况是在第一个操作完成之前超时。如果超时了,那么会使用CancellationToken来取消第一个操作。
然后我们向线程池中放入一个耗时长的操作。它会运行6秒钟,如果成功完
成则会设置一个ManualResetEvent信号类。在其他情况下,比如需要取消该操作,那么该操作会被丢弃。
最后,为操作提供5秒的超时时间是不够的。这是因为操作会花费6秒来完成,只能取消该操作。所以如果提供7秒的超时时间是可行的,该操作会顺利完成。
3.6.4 更多信息
当有大量的线程必须处于阻塞状态中等待一些多线程事件发信号时,以上方式非常有用。借助于线程池的基础设施,我们无需阻塞所有这样的线程。可以释放这些线程直到信号事件被设置。在服务器端应用程序中这是个非常重要的应用场景,因为服务器端应用程序要求高伸缩性及高性能。