为什么我不能重复使用WebClient进行相同的请求?

8

因此,以下代码:

        const long testCount = 2;
        const string jsonInput = "{\"blockId\":\"1\",\"userId\":\"{7c596b41-0dc3-45df-9b4c-08840f1da780}\",\"sessionId\":\"{46cd1b39-5d0a-440a-9650-ae4297b7e2e9}\"}";

        Stopwatch watch = Stopwatch.StartNew();

        using (var client = new WebClient())
        {
            client.Headers["Content-type"] = "application/json";
            client.Encoding = Encoding.UTF8;

            for (int i = 0; i < testCount; i++)
            {
                var response = client.UploadString("http://localhost:8080/BlocksOptimizationServices/dataPositions", "POST", jsonInput);
            }

            watch.Stop();
            double speed = watch.ElapsedMilliseconds / (double)testCount; 
            Console.WriteLine("Avg speed: {0} request/ms", testCount);

为了进行性能测试,我只想多次调用client.UploadString("http://localhost:8080/BlocksOptimizationServices/dataPositions", "POST", jsonInput)。但是在第一次请求之后,它总是失败并显示

“远程服务器返回错误:(400)错误的请求。”

如果我处理WebClient并重新创建它-可以工作,但这会增加额外的性能损失..为什么我不能重用WebClient两次?


4
你是否已经运行了 Fiddler 并进行了两次比较请求?后续的请求明显已经到达服务器以接收 400 错误。 - Alex K.
2个回答

12

每个请求后,WebClient标头都会被清除。您可以添加几个Debug.Assert()语句以自行查看。这与第二个请求中出现的“(400)错误请求”一致:

for (int i = 0; i < testCount; i++)
{
      Debug.Assert(client.Headers.Count == 1); // Content-type is set   
      var response = client.UploadString("http://localhost:8080/BlocksOptimizationServices/dataPositions", "POST", jsonInput);    
      Debug.Assert(client.Headers.Count == 0); // Zero!
}

所以,您可以更改代码以每次设置标头:

using (var client = new WebClient())
{            
    for (int i = 0; i < testCount; i++)
    {
        client.Headers["Content-type"] = "application/json";
        client.Encoding = Encoding.UTF8;

        var response = client.UploadString("http://localhost:8080/BlocksOptimizationServices/dataPositions", "POST", jsonInput);
    }

如果我释放WebClient并重新创建,则可以正常工作,但这会增加额外的性能损耗...为什么我不能重复使用WebClient两次?

这里有一个 Stack Overflow 的帖子认为每个请求实例化一个 WebClient 并不会带来太大的性能损耗:WebClient construction overhead

祝好运!


1
这可能不是你想要的,但这是我解决这个问题的方法。
public WebClient WebClient
                => new WebClient {Headers = new WebHeaderCollection {{HttpRequestHeader.ContentType, "application/json"}}};

每次使用它都会创建一个新的WebClient。这种方法可能对您来说不是很有效,但对于我使用它的目的来说效果很好,并且消除了为每个请求设置标题的需要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接