【发布时间】:2015-06-25 14:08:00
【问题描述】:
我一直在使用 System.Threading.Task 和 System.Net.Http.HttpClient 对 Web 服务器进行负载测试,并观察到一些奇怪的行为。代码如下:
var taskArray = new List<Task>();
for (int i = 0; i < 105; i++)
taskArray.Add(Task.Factory.StartNew(() => Get("/content/test.jpg")));
Task.WaitAll(taskArray.ToArray());
即使每个请求(通过提琴手监控时)只需要大约 15 毫秒的时间来执行,我还是收到了由用于发出请求的 HttpClient 引发的超时异常(嗯,TaskCanceledExcpetions - 这是同一件事)。请求时间超过了 100 秒的默认超时时间。
我尝试的第一件事是增加 HttpClient 的超时,这很有效,但我仍然难以理解为什么响应时间很短的请求会超时。因此,我在调用 HttpClient.PostAsync 之前设置了一个计时器,并检查了完成所需的时间,正如怀疑的那样,时间超过了 100 秒,尽管服务器发送响应的速度要快得多。
然后我读到 HttpClient.Timeout 是整个异步操作的超时时间,这让我认为可能是任务调度程序导致我出现问题,因为它仅在响应准备好后执行接收响应的异步回调很长时间收到。
考虑到这一点,我决定使用旧的 System.Threading.Thread 编写代码:
var handle = new EventWaitHandle(false, EventResetMode.ManualReset);
for (int i = 0; i < 105; i++)
{
var t = new Thread(() =>
{
Get("/content/test.jpg");
if (Interlocked.Decrement(ref numberOfTasks) == 0)
handle.Set();
});
t.Start();
}
handle.WaitOne();
这按预期工作!我什至可以将线程数增加到 2000,它完成所有线程的速度比基于任务的版本发送 105 更快!
什么给了?
【问题讨论】:
-
发布获取代码。您是否增加了 .NET HTTP 限制?
-
获取代码是:httpClient.GetAsync(url).Result 既然我已经看过这个,也许我应该尝试等待该操作,而不是阻塞结果....应该有发现了!是的,我确实尝试通过 ServicePointManager 提高限制,但没有帮助。
标签: c# multithreading task-parallel-library dotnet-httpclient