咨询区

  • boot4life

为了能够复用 HttpClient 所打开的TCP链接,我不得不让所有的request共享一个单例,但问题来了,如果我简单的在每一次request之前修改 timeout 属性的话,会存在下面两个问题。

  1. 线程不安全。

  2. 并发时可能会错用到其他 request 的超时配置。

请问我该如何正确的处理?

回答区

  • Todd Menier

你说的这种场景理论上是不可以设置 Timeout 属性,但不要忘了,你可以用 .NET 库中提供的取消机制类 CancellationTokenSource,你可以在每一次 request 中带入 token 即可,然后用 CancelAfter() 方法来实现 Timeout 的功能,参考如下代码:

static async Task Main(string[] args){var httpClient = new HttpClient();var cts = new CancellationTokenSource();cts.CancelAfter(TimeSpan.FromSeconds(30));await httpClient.GetAsync("http://www.google.com", cts.Token);}

哦,对了, HttpClient 的默认超时时间是 100s,如果你在 CancelAfter 中设置了过大的超时时间,本质上来说并没有效果,为了解决这个 Max 的问题,我建议你给 HttpClient 设置一个无限期的超时,参考代码如下:

static async Task Main(string[] args){var httpClient = new HttpClient();httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;var cts = new CancellationTokenSource();cts.CancelAfter(TimeSpan.FromSeconds(30));await httpClient.GetAsync("http://www.google.com", cts.Token);}
  • Brad Albright

楼上的大佬说的非常好,但在我的场景下是这么实现的,首先我有一个默认的 CancellationToken ,它可被用户手工干预,另外还有一个 CancellationToken,它是为了模拟 timeout 的 CancelAfter ,然后通过 CancellationTokenSource.CreateLinkedTokenSource 来将两者结合起来,就可以做到既可以被 timeout 结束也可以被用户手工干预停止,下面是我的案例代码:

public async static Task<HttpResponseMessage> SendRequest(CancellationToken cancellationToken)
{var ctsForTimeout = new CancellationTokenSource();ctsForTimeout.CancelAfter(TimeSpan.FromSeconds(5));var cancellationTokenForTimeout = ctsForTimeout.Token;using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancellationTokenForTimeout)){try{return await httpClient.GetAsync("http://asdfadsf", linkedCts.Token);}catch{//just for illustration purposesif (cancellationTokenForTimeout.IsCancellationRequested){Console.WriteLine("timeout");}else if (cancellationToken.IsCancellationRequested){Console.WriteLine("other cancellation token cancelled");}throw;}}
}

点评区

说实话,用 CancellationToken 来替代 Timeout 机制确实是一个非常好的想法,如果大家细心的话,会发现 Framework 中很多涉及IO的操作都实现了这种 取消机制,值得大家好好研究学习,比如下面代码:

public Task<HttpResponseMessage> DeleteAsync(Uri? requestUri, CancellationToken cancellationToken);
public Task<byte[]> GetByteArrayAsync(string? requestUri, CancellationToken cancellationToken);
public Task<Stream> GetStreamAsync(Uri? requestUri, CancellationToken cancellationToken);
public Task<string> GetStringAsync(string? requestUri, CancellationToken cancellationToken);
public Task<HttpResponseMessage> PutAsync(Uri? requestUri, HttpContent content, CancellationToken cancellationToken);
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);

如何在并发中给 HttpClient 设置不同的超时时间?相关推荐

  1. httpclient: 设置请求的超时时间,连接超时时间等

    1.为什么要设置HTTP timeout? 1.与用户操作相关的接口,如果不设置超时时间,将会出现长时间的无响应,严重影响用户体验. 2.负载很高的系统,因为大量调用耗时长的接口,导致性能急剧下降,从 ...

  2. 网页 服务器长连接超时时间,服务器设置长连接超时时间

    服务器设置长连接超时时间 内容精选 换一换 有以下几种现象:将制作好的SD卡插入开发者板并上电后,开发者板LED1与LED2灯状态信息异常.将制作好的SD卡插入开发者板,并通过USB方式连接Ubunt ...

  3. 服务器时间修改连接超时时间,服务器设置网络连接超时时间设置

    服务器设置网络连接超时时间设置 内容精选 换一换 有以下几种现象:将制作好的SD卡插入开发者板并上电后,开发者板LED1与LED2灯状态信息异常.将制作好的SD卡插入开发者板,并通过USB方式连接Ub ...

  4. Jedis 设置key的超时时间

    一分钟之内只能发送一次短信, 若用户刷新页面,然后输入原来的手机号,则继续计时 方案:服务器端要记录时间戳 方法名:sMSWaitingTime 功能:返回倒计时剩余时间,单位秒 Java代码   / ...

  5. linux设置ssh连接超时时间

    linux设置ssh连接超时时间 第一步: 修改/root/.bash_profile文件,新增export TMOUT=1000000(以秒为单位) 第二步: 让这个修改过后的文件生效 source ...

  6. php 设置curl不超时时间,curl命令的超时时间

    今天在一台服务器上突然看到一个curl进程已经运行了28天还木结束, 有点奇怪! 我在使用curl的时候也设置了超时时间, --connect-timeout 5 curl --connect-tim ...

  7. 设置TCP connect超时时间的2种方法

    1.常用方法 设置socket非阻塞,之后使用select等设置超时时间 2.使用alarm信号量 需要注意:线程信号量掩码是线程私有的,当指定进程递交信号量时,操作系统会将信号量递交至该进程中未屏蔽 ...

  8. ajax谷歌浏览器提示等待超时,调用谷歌浏览器爬虫,selenium webdriver等设置等待时间和超时时间...

    selenium webdriver超时设置分三类 pageLoadTimeout,setScriptTimeout,implicitlyWait 1.  pageLoadTimeout: pageL ...

  9. springboot 使用 redis 监听 key 的过期回调( 模拟设置订单号超时时间, 触发修改订单状态业务逻辑)

    本文Demo地址:https://gitee.com/wslxm/spring-boot-redis 一.redis 配置文件 redis.conf 修改如下 notify-keyspace-even ...

最新文章

  1. 手工安装kubernetes
  2. checkVector()
  3. 又一次的Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat)
  4. 构造器初始化(三):巧用Static方法和base关键字
  5. 安装JAVA 运行环境
  6. OOP接口与抽象类的区别
  7. 小程序学习(一):点击爱心变色 -- 最简单的事件实现
  8. 【项目调研+论文阅读】(目录)中文实体识别研究方法综述 day6
  9. jquery ajax 上传文件报错,jQuery :ajaxfileupload+Struts2 文件上传,报错data undefined
  10. python爬取学校题库_利用Python网络爬虫爬取学校官网十条标题
  11. 软件设计原则之单一职责原则
  12. 计算机二级试题操作题图文讲解,计算机二级Word篇-实操真题详解26
  13. 常用的不透明度的值,以黑色为例
  14. 2017中国开发者调查报告-云栖社区
  15. C# WPF、Winform中Show()和ShowDialog()区别
  16. ##gif录制软件——初识GifCam##
  17. python和易语言哪个容易胖_坐着长肉还是躺着长肉 哪个更容易胖
  18. python和C++
  19. CentOS7系统之间设置共享文件夹
  20. 服务器文件管理系统破解版,Cerberus FTP Server Enterprise

热门文章

  1. mysql语法学习(一)__Instances__表
  2. SAP MM 采购订单收货被取消了还是不能增加新的delivery cost!
  3. h5c3 part6 flex
  4. supervisord的安装使用
  5. 01: 实现注册登录功能
  6. java 动态代理
  7. SAP ECC EHP7 RFC 发布成WebService
  8. (第九周)团队项目14
  9. lr java脚本_【上海校区】 LR Java脚本编写方法
  10. 如何在Chrome工具栏中固定和取消固定扩展程序