使用Task.Wait和Cancel解决Remoting超时Timeout问题
2012-03-21 22:03
337 查看
在Remoting客户端用TcpChannel链接服务端的时候,如果地址不存在会尝试连接到超时Timeout大概21秒左右,例如连接到"tcp://192.192.192.192:8080/ServerObject"这个不存在的Remoting service地址。如何才能缩短这个Remoting超时Timeout的时间呢?根据MSDN Channel Properties说明:默认的timeout设置是infinite(无限),默认失败尝试次数/retryCount是一次。所以很自然,设置Remoting客户端用TcpChannel链接服务端的连接超时timeout在timeout参数里面,代码是这样的:
接下来的代码就是调用instance的方法(IMyServiceContract里面定义的)。
可是测试发现设置的timeout参数没起作用,超时还是21秒。
后来网上搜了一下,的确这是个普遍的问题,看看这个和这个帖子,但可惜都没有解决我的问题。网上都没有好的办法,无奈我只好自己搞定了。用.NET 4.0 TPL里面的Task.Wait(timeSpan)和cancel搞定。
我想你一定看懂了,意思就是,线程池启动一个线程,做一些事情(这里假设耗时4秒),但必须在超时时间timeout时间内(这里是3秒)内完成,timeout时间到了就取消该线程任务,并返回false。如果操作在3秒内完成了,那么久返回true。很简单吧。
(注:这里用了CancelationTokenSource.Cancel()来取消线程任务,并且结合TPL里面的Task.Wait(timeSpan),这样实现timeout时间到了就取消该线程任务。请参考MSDN:Task Cancelation 和How to: Cancel a Task and Its Children. 细节:如果仅仅调用bool Wait(TimeSpan timeout),时间到了并不会停止任务执行,而是等待任务执行完成,看所用时间如果超过timespan就返回false,否则返回true。)
这个方法就是用来测试一个远程地址是否可用,比如连接到"tcp://192.192.192.192:8080/ServerObject"这个不存在的Remoting service地址,如果能在timeout时间内(例如3秒内)返回,那么测试成功。超过就是失败的服务端地址。可以在上面do some task的地方放置你的耗时操作,例如 Activator.GetObject 或者 instance.dosomething() - 一定要用try-catch括起来哦。
原因是如果连接到"tcp://192.192.192.192:8080/ServerObject"这个不存在的Remoting service地址,可能会在Activator.GetObject 或者 instance.dosomething()这一步出现connection failed的异常,提示远程remoting服务器连接不上,然后就走到catch里面调用了ChannelServices.UnregisterChannel了吗?没有,还有retryCount,失败重试,所以实际并没有执行注销channel。
正确的解决方法是在其他地方,或者过一会儿再调用ChannelServices.UnregisterChannel。或者在我上述的函数测试一个远程地址是否可用TestRemotingServerAddress调用完成以后,如果是false,就调ChannelServices.UnregisterChannel。此外,如果endpoint地址改变了,需要调用ChannelServices.UnregisterChannel,否则会发生异常。
接下来的代码就是调用instance的方法(IMyServiceContract里面定义的)。
可是测试发现设置的timeout参数没起作用,超时还是21秒。
后来网上搜了一下,的确这是个普遍的问题,看看这个和这个帖子,但可惜都没有解决我的问题。网上都没有好的办法,无奈我只好自己搞定了。用.NET 4.0 TPL里面的Task.Wait(timeSpan)和cancel搞定。
使用Task.Wait和Cancel解决Remoting超时Timeout问题
先看看下面的代码:我想你一定看懂了,意思就是,线程池启动一个线程,做一些事情(这里假设耗时4秒),但必须在超时时间timeout时间内(这里是3秒)内完成,timeout时间到了就取消该线程任务,并返回false。如果操作在3秒内完成了,那么久返回true。很简单吧。
(注:这里用了CancelationTokenSource.Cancel()来取消线程任务,并且结合TPL里面的Task.Wait(timeSpan),这样实现timeout时间到了就取消该线程任务。请参考MSDN:Task Cancelation 和How to: Cancel a Task and Its Children. 细节:如果仅仅调用bool Wait(TimeSpan timeout),时间到了并不会停止任务执行,而是等待任务执行完成,看所用时间如果超过timespan就返回false,否则返回true。)
这个方法就是用来测试一个远程地址是否可用,比如连接到"tcp://192.192.192.192:8080/ServerObject"这个不存在的Remoting service地址,如果能在timeout时间内(例如3秒内)返回,那么测试成功。超过就是失败的服务端地址。可以在上面do some task的地方放置你的耗时操作,例如 Activator.GetObject 或者 instance.dosomething() - 一定要用try-catch括起来哦。
需要注意ChannelServices.UnRegisterChannel
有一点需要注意ChannelServices.UnregisterChannel,如果放在try-catch的那个block里面的话可能不工作,没有效果,看下面的代码:原因是如果连接到"tcp://192.192.192.192:8080/ServerObject"这个不存在的Remoting service地址,可能会在Activator.GetObject 或者 instance.dosomething()这一步出现connection failed的异常,提示远程remoting服务器连接不上,然后就走到catch里面调用了ChannelServices.UnregisterChannel了吗?没有,还有retryCount,失败重试,所以实际并没有执行注销channel。
正确的解决方法是在其他地方,或者过一会儿再调用ChannelServices.UnregisterChannel。或者在我上述的函数测试一个远程地址是否可用TestRemotingServerAddress调用完成以后,如果是false,就调ChannelServices.UnregisterChannel。此外,如果endpoint地址改变了,需要调用ChannelServices.UnregisterChannel,否则会发生异常。
相关文章推荐
- 解决AJAX应用,会话超时(Session Timeout)的问题,粗略方法(不考虑使用Filter的前提下)
- php使用mysql-timeout包,解决sql语句查询超时问题
- 解决hung_task_timeout_secs问题【方法待校验】
- 关于MySQL的wait_timeout连接超时问题报错解决方案
- C3P0连接池+MySQL的配置以及wait_timeout问题的解决
- 解决使用MySQL C-API开发应用时的连接超时问题
- xmemcached与spring结合使用时连接超时问题解决方法(转)
- 【问题解决:死锁】Lock wait timeout exceeded; try restarting transaction的问题
- 关于MySQL的wait_timeout连接超时问题报错解决方案
- 使用halcon解决工业相机外部触发模式下的超时问题
- 解决:使用java连接Fastdfs,上传文件时报:SocketTimeOutException的问题.
- CountDownTimer的使用以及解决Cancel无效的问题
- 解决使用MySQL C-API开发应用时的连接超时问题
- 如何解决阿里云服务器使用phpmail发送邮件超时的问题(针对qq企业邮箱)
- sublime text3 插件sftp使用方法 快捷键 timeout connect 连接超时解决
- 在从池中获取连接之前超时时间已过,所有池连接都已被使用并已达到最大池大小的问题解决方法
- 解决Mac下使用iTerm连接远程机器超时自动断开的问题
- 解决使用HttpWebRequest时总是提示登陆超时的问题
- spring3使用task注记及task:annotation-driven解决定时问题
- java使用Jsoup连接网站超时的解决方法 链接的时候设定超时时间即可。 doc = Jsoup.connect(url).timeout(5000).get();