C# 采集 :设计一个可超时的阻塞方法
2008-10-30 00:34
309 查看
有时候我们调用一个第三方的会阻塞的方法,我们要想法做一个调用超时值,一般来说就是另起一个线程加join的办法,这里有另外一种思路,但也不是完全的解决办法,希望大家多多讨论。
下面是咱们的一个方法,很简单,一个执行方法,一个终止方法,一个和执行方法签名相同的公开委托。
class MyHelper
上面的类的Excute方法是阻塞的,如果传入的a参数是一个特别大的值,调用这个方法的代码会阻塞很长的时间,如果客户端的很多请求都要调用这个方法,而且你的系统实现了多线程,用线程池线程来处理用户的每一个请求,这就有问题了,没过多久,你的线程池就耗尽了。这时候用下面的办法可以加上一个超时逻辑。
private static void InvokeExcute()
以上的示例代码调用的Excute方法要执行5秒,而我们设置了3秒的超时时间,到了3秒咱们就终止调用。以后如果自己要写这种可能会阻塞的方法就加一个Abort的方法来终止操作并清理资源,像HttpWebRequest类就是这么设计的,有一个Abort方法。
但是:如果这个会阻塞的方法不是你写的,是第三方提供的,而且还没有Abort方法,这时候虽然RegisterWaitForSingleObject的超时回调会执行,但是BeginInvoke执行的委托还会在线程池里继续执行,也就是还是有可能把线程池耗尽,我的建议是对于不了解的第三方方法,或者已知会阻塞的方法,不要让线程池去调用它。线程池适合处理那种快速返回的方法。
再有一个人们就说了,我自己实现一套线程池,线程池里执行一个方法超时后,我就调用Thread.Abort来终止这个线程,呵呵,想的倒挺好,.net里如果有个线程调用了非托管的代码,如果你Abort了这个线程,这个线程不会立刻抛出ThreadAbort异常,而会等待非托管代码返回托管代码才会抛出异常,那你还是没解决问题。像这种情况很多,就说常用的Socket.BeginConnect吧,虽说是异步的,可也是有可能阻塞个几十秒的,其实大多时间在DNS解析上。像这种问题,基本上没解,除非你自己去重写Windows的Socket实现去吧,貌似用c++写的Socket.connect函数也不好控制超时参数,也是用消息循环或者多个线程来实现,说是有个注册表键值,貌似也不怎么管用。
总结:很郁闷,没找到答案,也许我把问题想复杂了。
参考链接:http://morganchengmo.spaces.live.com/blog/cns!9950CE918939932E!1586.entry
强烈建议dudu自动把http开头的文字加上超链接,每次我还得自己加。
下面是咱们的一个方法,很简单,一个执行方法,一个终止方法,一个和执行方法签名相同的公开委托。
class MyHelper
上面的类的Excute方法是阻塞的,如果传入的a参数是一个特别大的值,调用这个方法的代码会阻塞很长的时间,如果客户端的很多请求都要调用这个方法,而且你的系统实现了多线程,用线程池线程来处理用户的每一个请求,这就有问题了,没过多久,你的线程池就耗尽了。这时候用下面的办法可以加上一个超时逻辑。
private static void InvokeExcute()
以上的示例代码调用的Excute方法要执行5秒,而我们设置了3秒的超时时间,到了3秒咱们就终止调用。以后如果自己要写这种可能会阻塞的方法就加一个Abort的方法来终止操作并清理资源,像HttpWebRequest类就是这么设计的,有一个Abort方法。
但是:如果这个会阻塞的方法不是你写的,是第三方提供的,而且还没有Abort方法,这时候虽然RegisterWaitForSingleObject的超时回调会执行,但是BeginInvoke执行的委托还会在线程池里继续执行,也就是还是有可能把线程池耗尽,我的建议是对于不了解的第三方方法,或者已知会阻塞的方法,不要让线程池去调用它。线程池适合处理那种快速返回的方法。
再有一个人们就说了,我自己实现一套线程池,线程池里执行一个方法超时后,我就调用Thread.Abort来终止这个线程,呵呵,想的倒挺好,.net里如果有个线程调用了非托管的代码,如果你Abort了这个线程,这个线程不会立刻抛出ThreadAbort异常,而会等待非托管代码返回托管代码才会抛出异常,那你还是没解决问题。像这种情况很多,就说常用的Socket.BeginConnect吧,虽说是异步的,可也是有可能阻塞个几十秒的,其实大多时间在DNS解析上。像这种问题,基本上没解,除非你自己去重写Windows的Socket实现去吧,貌似用c++写的Socket.connect函数也不好控制超时参数,也是用消息循环或者多个线程来实现,说是有个注册表键值,貌似也不怎么管用。
总结:很郁闷,没找到答案,也许我把问题想复杂了。
参考链接:http://morganchengmo.spaces.live.com/blog/cns!9950CE918939932E!1586.entry
强烈建议dudu自动把http开头的文字加上超链接,每次我还得自己加。
相关文章推荐
- 蛙蛙推荐:设计一个可超时的阻塞方法
- C#: 一个方法执行超时 timeout 检查的实现
- 用C#构建一个简单的采集系统之一-主界面设计
- 一个获取相对路径的方法(C#)
- Requirejs加载超时问题的一个解决方法:设置waitSeconds=0
- 一个典型的采集服务器体系结构设计
- 一个开源的IoC采集服务器体系结构设计
- 一个开源的IoC采集服务器体系结构设计
- [C#]调用方法判断一个整数是否为质数
- 简单干净的C#方法设计案例:SFCUI.AjaxLoadPage()之一
- 简单干净的C#方法设计案例:SFCUI.AjaxLoadPage()之二
- C#程序多用户只启动一个进程的方法[转载]
- C# 一个图片上传的简单方法
- C#连接服务器超时解决方法
- Canvas画弧线方法(不知道的时候自己设计算法,结果一个悲剧啊。)
- 判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)
- java 面试题 请设计一个方法,可以实现获取任意范围内的随机数
- C#--2.继续在该类中编写一下方法,名称为Reconvert,参数一个,但可以是字符串、整数、单精度、双精度,方法功能返回参数的逆序。
- C# 调用lua 报错未能加载文件或程序集“lua51.dll”或它的某一个依赖项。找不到指定的模块。 解决方法
- C#基础篇 重写与重载,以及其中设计的虚方法和抽象方法的使用和区别