.net 是否有正确的方法来处理 httpwebrequest?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/716436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:27:54  来源:igfitidea点击:

Is there a correct way to dispose of a httpwebrequest?

.nethttpwebrequest

提问by mickyjtwin

I am using a HttpWebRequest, and am disposing of the response stream. Is there a correct method of disposing of the HttpWebRequest, as it does not contain a close or dispose method?

我正在使用HttpWebRequest, 并且正在处理响应流。是否有正确的处理方法HttpWebRequest,因为它不包含 close 或 dispose 方法?

回答by John Saunders

If the class had special disposal requirements, it would have implemented IDisposable. Since it doesn't implement IDisposable, you may assume there's nothing special you need to do.

如果该类有特殊的处理要求,它就会实现 IDisposable。由于它没有实现 IDisposable,您可能会认为没有什么特别的事情需要做。

回答by David Wohlferd

I had a similar question, and the answers here did not give me the information I needed. So even though there is an accepted answer, I'm going to add what I've learned to help the next guy.

我有一个类似的问题,这里的答案没有给我我需要的信息。因此,即使有一个公认的答案,我也会添加我所学到的知识来帮助下一个人。

1) As some of the other answers mention, you can use usingfor the streams returned from HttpWebRequest/WebRequest. This is just good standard c# programming.

1)正如其他一些答案所提到的,您可以using用于从 HttpWebRequest/WebRequest 返回的流。这只是很好的标准 c# 编程。

But it doesn't really address the OP's question (or mine), which was about the disposing of the HttpWebRequest object itself.

但它并没有真正解决 OP 的问题(或我的问题),即关于 HttpWebRequest 对象本身的处理。

2) Despite the fact that the function to acquire an HttpWebRequest is named 'Create,' there is no matching Destroy, Close, Dispose, or any other mechanism available to free the resources from the created object.

2) 尽管获取 HttpWebRequest 的函数名为“Create”,但没有匹配的 Destroy、Close、Dispose 或任何其他机制可用于从创建的对象中释放资源。

This is basically the currently accepted answer.

这基本上是目前公认的答案。

3) But there is an implication among all the answers here that (other than the streams) there isn't anything important left hanging around that needsto be closed. And that is not entirely correct.

3)但是这里的所有答案都暗示着(除了流之外)没有任何重要的东西需要关闭。这并不完全正确。

Using ProcMon, you can see the TCP Connect, TCP Sendand TCP Receivethat occur when you call GetResponse(). This is what I would expect to see. But when does the TCP Disconnectoccur? My assumption was that this would happen either after you finished receiving the response, or at worst when the object gets GC'ed. But the reality is more interesting.

使用procmon中,你可以看到TCP ConnectTCP SendTCP Receive当你调用发生GetResponse()。这是我希望看到的。但是什么时候TCP Disconnect发生呢?我的假设是,这会在您完成接收响应后发生,或者最坏的情况是在对象被 GC 处理后发生。但现实更有趣。

Instead, the TCP connection remains active for exactly 2 minutes after the call. My first thought was that's just how long it takes for the GC to get around to it, but nope. You can sit there in a GC.Collect() loop for those 2 minutes, and it doesn't let go until the 2 minutes are up. This keeps the connection open on both the client and the server, and causes (some) additional network traffic for those 2 minutes to keep the connection alive.

相反,TCP 连接在呼叫后恰好 2 分钟内保持活动状态。我的第一个想法是 GC 需要多长时间才能解决它,但不是。您可以在 GC.Collect() 循环中等待那 2 分钟,直到 2 分钟结束它才会松手。这使客户端和服务器上的连接都保持打开状态,并在这 2 分钟内导致(一些)额外的网络流量以保持连接处于活动状态。

Another interesting thing is that even though you are calling 'Create', that doesn't mean another TCP connection necessarily gets created. For instance, consider this:

另一个有趣的事情是,即使您正在调用“创建”,这并不意味着必然会创建另一个 TCP 连接。例如,考虑这个:

static void Doit(string domain)
{
    HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(domain);

    using (HttpWebResponse response = (HttpWebResponse)hr.GetResponse())
        using (Stream receiveStream = response.GetResponseStream())
            using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
                Console.WriteLine(readStream.ReadToEnd());
}

Now, if I call this with:

现在,如果我用以下方式调用它:

Doit("http://www.foo.bar");

It will create 1 TCP connection. It will stay active for 2 minutes (or until the program exits). But what if I do this:

它将创建 1 个 TCP 连接。它将保持活动状态 2 分钟(或直到程序退出)。但如果我这样做:

Doit("http://www.foo.bar");
Thread.Sleep(20000);
Doit("http://www.foo.bar");

Now it will create 1 connection for the first call, then reusethat connection for the second call. Meaning the TCP connection will stay active for 2:20 minutes total. So even though we are calling 'Create,' it's not creating a connection from scratch.

现在它将为第一个调用创建 1 个连接,然后在第二个调用中重复使用该连接。这意味着 TCP 连接将总共保持活动 2:20 分钟。因此,即使我们调用了“创建”,它也不是从头开始创建连接。

Mostly this is a good thing. Making a connection (especially an HTTPS connection) can be an expensive process. A system that automatically avoids that for you is (probably) a good thing. That way you can efficiently retrieve the html for a web page, then any of the related support files (css, img files, etc) without having to go through the connect process each time.

大多数情况下,这是一件好事。建立连接(尤其是 HTTPS 连接)可能是一个昂贵的过程。一个自动避免这种情况的系统(可能)是一件好事。这样您就可以高效地检索网页的 html,然后是任何相关的支持文件(css、img 文件等),而无需每次都经过连接过程。

But what if the server you are connecting to only supports a limited number of connections? Leaving a connection tied up like this for no good reason could be a real problem. Or perhaps for security reasons, you can't be leaving connections open for that long? Or maybe you're just anal and want to shut the thing down as soon as you are done with it.

但是如果您连接的服务器只支持有限数量的连接呢?无缘无故地将连接像这样捆绑起来可能是一个真正的问题。或者可能出于安全原因,您不能让连接打开那么长时间?或者,也许您只是肛门,并且想在完成后立即关闭它。

For these cases, you can experiment with HttpWebRequest.KeepAlive. Setting this to false(the default is true) causes each of the examples above to each use their own connection, shutting them down as soon as you are done. The entire Connect/Send/Receive/Disconnect process can thus complete in less than a second.

对于这些情况,您可以尝试使用HttpWebRequest.KeepAlive. 将此设置为false(默认为true)会导致上面的每个示例都使用自己的连接,并在完成后立即关闭它们。因此,整个连接/发送/接收/断开过程可以在不到一秒的时间内完成。

FYI:

供参考:

  • While you can use WebRequest.InitializeLifetimeService to get an ILease, changing the values on the lease does not affect the timeouts here.
  • Instead of using WebRequest, you can use WebClient, which does support Dispose. However the underlying TCP connection still hangs around for 2 minutes even after calling Dispose.
  • 虽然您可以使用 WebRequest.InitializeLifetimeService 来获取 ILease,但更改租约上的值不会影响此处的超时。
  • 您可以使用支持 Dispose 的 WebClient,而不是使用 WebRequest。然而,即使在调用 Dispose 之后,底层 TCP 连接仍会挂起 2 分钟。

In conclusion: Saying that you don't need to worry about shutting down an HttpWebClient may be generally true, but there are implications you might want to be aware of. There are good reasons for this behavior, but you cannot decide whether this is good for your particular application if you don't know it is happening.

结论:说您不必担心关闭 HttpWebClient 可能通常是正确的,但您可能需要注意其中的一些含义。这种行为有很好的理由,但如果您不知道它正在发生,则无法确定这是否对您的特定应用程序有益。

FWIW

FWIW

回答by Joshua

httpwebRequest doesn't implement IDisposable since it can create a Stream, which does implement IDisposable. As such, you shouldnt worry about disposing it.

httpwebRequest 没有实现 IDisposable,因为它可以创建一个 Stream,它确实实现了 IDisposable。因此,您不必担心处理它。

If you are worried though, you may want to use WebClient, which is IDisposable:

如果您担心,您可能想使用 IDisposable 的 WebClient:

using (WebClient c = new WebClient())
{
using (Stream stream = c.OpenRead(url))
{
//
}
}

回答by Kevin M

You can use:

您可以使用:

    var webRequest = WebRequest.Create(ActionUrl)
    using (var webResponse = webRequest.GetResponse())
    {}

for your implementation. When I've used the WebRequest class to fire off multiple requests in a very short timeframe, wrapping the GetResponse() in a using block is what prevented the app from hanging up.

为您的实施。当我使用 WebRequest 类在很短的时间内触发多个请求时,将 GetResponse() 包装在 using 块中是防止应用程序挂断的原因。

回答by Kevin M

HttpWebRequest does not implement IDisposable so it does not require disposing. just set the httprequest object to null once your done with it.

HttpWebRequest 没有实现 IDisposable 所以它不需要处理。完成后,只需将 httprequest 对象设置为 null 即可。

Hope it helps

希望能帮助到你