如何在 C# 中为大型 HTTP 请求设置 HttpWebRequest.Timeout

2024-03-02

我不知道如何处理 HttpWebRequest.Timeout。之前,我曾经为 Socket 对象设置超时,这很简单:超时设置发送或接收数据块的最长时间。然而,HttpWebRequest.Timeout 似乎设置了整个 HTTP 请求的超时。如果请求很大(例如,我使用 HTTP PUT 上传一个大文件),则可能需要几个小时。这导致我进行设置:

...
request.Timeout = System.Threading.Timeout.Infinite;
Stream requestStream = request.GetRequestStream();
for (something)
{
  ...
  requestStream.Write(b, 0, b.Length);
}

但是,这是否意味着如果与服务器的网络连接被卡住,我最终会得到 requestStream.Write 永远不会抛出“操作超时”异常?那么超时的概念在这种情况下不起作用吗?

理想情况下,我希望 .Timeout 设置仅影响单个 requestStream.Write。我可以根据需要拥有任意数量的 Write() ,前提是每个 Write() 的值永远不会超过 .Timeout 值。

或者我是否需要实现自己的基于 Socket 的机制来实现这一目标?

另外,在设置断点时,我发现requestStream实际上是具有.Timeout=300000(300秒)的ConnectStream实例。这是否意味着 Infinite 实际上并不是无限的,并且仅限于 300 秒?对于大文件和慢速连接来说,这是相当严格的限制。


在处理大文件上传时,有两个超时困扰着我们。HttpWebRequest.Timeout and HttpWebRequest.ReadWriteTimeout。我们需要解决both.

HttpWebRequest.ReadWriteTimeout

首先我们先来说说HttpWebRequest.ReadWriteTimeout。我们需要禁用“写入流缓冲”。

httpRequest.AllowWriteStreamBuffering = false;

更改此设置后,您的HttpWebRequest.ReadWriteTimeout这些值会神奇地按照您希望的方式工作,您可以将它们保留为默认值(5 分钟),甚至减少它们。我用的是60秒。

出现这个问题的原因是,当上传大文件时,如果数据被.NET框架缓冲,你的代码会认为上传完成,但实际上并没有完成,并调用HttpWebRequest.GetResponse()太早了,会超时。

HttpWebRequest.Timeout

现在,我们来解决HttpWebRequest.Timeout.

我们的第二个问题的出现是因为HttpWebRequest.Timeout适用于整个上传。上传过程实际上包括三个步骤(这是一篇很棒的文章,是我的主要参考 http://www.thomaslevesque.com/2014/01/14/tackling-timeout-issues-when-uploading-large-files-with-httpwebrequest/):

  1. 请求start上传。
  2. 字节的写入。
  3. 请求finish上传并从服务器获取任何响应。

如果我们有一个适用于整个上传的超时,我们需要大量的超时来容纳大文件的上传,但我们也面临一个问题,即合法的超时将需要很长时间才能真正超时。这不是一个好情况。相反,我们希望在步骤 #1 和 #3 中应用较短的超时时间(例如 30 秒)。我们根本不希望 #2 出现整体超时,但我们确实希望如果字节在一段时间内停止写入,则上传失败。值得庆幸的是,我们已经解决了#2HttpWebRequest.ReadWriteTimeout,我们只需要修复恼人的行为HttpWebRequest.Timeout。事实证明,异步版本GetRequestStream and GetResponse做我们需要的事情。

所以你想要这段代码:

public static class AsyncExtensions
{
    public static Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout)
    {
        return Task.Factory.StartNew(() =>
        {
            var b = task.Wait((int)timeout.TotalMilliseconds);
            if (b) return task.Result;
            throw new WebException("The operation has timed out", WebExceptionStatus.Timeout);
        });
    }
}

而不是打电话GetRequestStream and GetResponse我们将调用异步版本:

var uploadStream = httpRequest.GetRequestStreamAsync().WithTimeout(TimeSpan.FromSeconds(30)).Result;

对于响应也类似:

var response = (HttpWebResponse)httpRequest.GetResponseAsync().WithTimeout(TimeSpan.FromSeconds(30)).Result;

这就是您所需要的。现在您的上传将更加可靠。您可以将整个上传包装在重试循环中以增加确定性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 C# 中为大型 HTTP 请求设置 HttpWebRequest.Timeout 的相关文章

随机推荐

  • 包含修订历史记录的 CouchDB 视图

    我对 CouchDB 很陌生 已经缺少 SQL 了 无论如何 我需要创建一个视图来发出文档的一些属性以及所有修订 ID 像这样的东西 function doc if doc type template emit doc owner id d
  • VS Xaml 设计器错误

    我的 WPF 应用程序中的 Xaml 文件出现错误 我无法在 Visual Studio 设计器或 Blend 中看到我的控件 但是 该应用程序可以完美编译并运行 在 Blend 中 它说存在无效的 Xaml 并且该错误根本没有任何意义 但
  • 尝试将本地页面加载到 JavaFX webEngine 中

    我的 JavaFX 应用程序的选项卡上有一个 webView 组件 我正在尝试将本地存储的 HTML 页面加载到 WebView browser new WebView WebEngine webEngine browser getEngi
  • 监听附加端口 Microsoft Azure Nodejs

    我正在端口 process env PORT 1337 Microsoft Azure 上的默认端口 上运行 Nodejs 应用程序 Azure Web App 我还需要监听 websocket 的附加端口 在我本地 我使用的是 8000
  • 如何禁用 DateTimePicker 控件上的某些日期?

    如何禁用选定的日期DateTimePicker这样用户就无法选择它们 我知道这在 Web 窗体中是可能的 但在 Windows 窗体中我无法执行此操作 我怎样才能实现这个目标 您执行此操作的难易程度取决于您想要限制的日期 例如 如果您只想指
  • 如何从 Android 电话簿中选择联系号码到我的应用程序中?

    全部 我想从我的应用程序数据库中的android电话簿中获取号码 我已经用下面的代码尝试过 但这里正在获取人名 而不是我想要电话簿中的号码并希望将其存储在我的数据库中 如何实现这一目标 任何人都可以指导我 Override public v
  • 如何存储通用引用

    我需要在类中存储通用引用 我确信引用的值将比类的寿命更长 有这样做的规范方法吗 这是我想出的一个最小的例子 它似乎有效 但我不确定我是否做对了 template
  • 实现按住连续事件触发的优雅方式?

    我经常需要通过按住按钮来触发一系列事件 想一个 增加字段的按钮 点击它应该将其增加 1 但点击并按住应该每秒增加 1 直到释放按钮 另一个示例是在音频播放器类型应用程序中按住后退或前进按钮时的擦洗功能 我通常采用以下策略 On touchD
  • 如何将带有键值对的列表转换为字典

    我想迭代这个列表 name test1 email email protected cdn cgi l email protection role test description test name test2 email email p
  • 嵌入式 Derby/Java DB 中的自动增量错误

    我正在开发一个在嵌入式模式下使用 Apache Derby 数据库的会计程序 我有一个包含两列的表 Branch CREATE TABLE Branch idBranch INT NOT NULL PRIMARY KEY GENERATED
  • 如何在Android中截断TextView,然后添加省略号

    我读过这里的一些其他线程也有类似的担忧 但他们的答案似乎都不适合我 无法在 Android 上使用省略号 https stackoverflow com questions 1698881 cant get ellipsis to work
  • 如何创建 ASP.NET 网站的移动版本?

    我有一个使用asp创建的网站 我想让手机可以访问它 这样用户就可以通过他 她的手机使用它 我对 XML 或 NET 没有任何了解 我怎样才能做到这一点 ASP NET 移动网页 https learn microsoft com en us
  • 如何在 VSTS 部署期间从 Azure Web App 删除文件

    我有一个 Azure Web 应用程序 我将一些数据存储在它的持久存储中 通过我的 VSTS 发布定义 我想删除一个填充了数据的文件夹 该文件夹位于D home site MyFolder 有没有办法可以在部署期间以编程方式从 VSTS 发
  • 哪里有一些好的 Xlib 编程指南?

    我现在对 Xlib 编程有点困惑 几周前我开始使用 dwm 一个轻量级窗口管理器 我想找一些 Xlib 编程书籍或在线资源来自定义 dwm 然而 在网上搜索后 我没有看到太多关于 Xlib 的新文章 亚马逊上最新的X窗口系统编程指南是199
  • 我的spark sql限制非常慢

    我使用spark从elasticsearch中读取 Like select col from index limit 10 问题是索引非常大 它包含 1000 亿行 而 Spark 会生成数千个任务来完成这项工作 我只需要 10 行 即使
  • 将 pyqtgraph 导出到视频

    我想将 pyqtgraph 导出到视频 有什么简单的方法可以做到这一点吗 该图与此示例没有太大区别 只是它包含大约 10000 帧 from pyqtgraph Qt import QtGui QtCore import numpy as
  • poi 中的 IRR 返回 NaN 但 excel 中的值正确

    当我使用 apache poi 计算 Irr 值时 我得到 Double NaN 但 excel 中的相同输入我得到负值 那么为什么它们返回不同的值呢 inputs here irr 1 0601017230994111E8 19150 6
  • React-native 链接找不到我的 MainApplication.java 文件

    每次我尝试react native link一个新的库 我收到同样的错误消息 这是用于react native video的 rnpm install info Linking react native video android depe
  • 为什么在 google chrome 浏览器中尝试时,javaScript 中的“navigator.userAgent”会返回字符串“Mozilla”?

    我正在开发 javaScript 代码 我想确定客户端浏览器的版本和品牌 这是我用来执行此操作的代码段 var browserName function BrowserCheckin if navigator userAgent index
  • 如何在 C# 中为大型 HTTP 请求设置 HttpWebRequest.Timeout

    我不知道如何处理 HttpWebRequest Timeout 之前 我曾经为 Socket 对象设置超时 这很简单 超时设置发送或接收数据块的最长时间 然而 HttpWebRequest Timeout 似乎设置了整个 HTTP 请求的超