gpt4 book ai didi

c# - 基于任务的并发比直接使用 System.Threading.Thread 慢得多

转载 作者:行者123 更新时间:2023-11-30 16:53:50 25 4
gpt4 key购买 nike

我一直在使用 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());

即使每个请求(当通过 fiddler 监控时)只需要大约 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 个更快!

什么给了?

最佳答案

正如 Matthew 所说,这是因为任务工厂默认使用线程池。如果您想使用任务并想提高线程池限制,则稍微提高限制或创建自己的线程池可能对您有一些值(value)。

也就是说,您已经在使用一个包含所有异步方法的类:为什么要尝试将它们包装在线程中?只需捕获任务并等待它们。

像这样:

var tasks = new List<Task>();              
for (int i = 0; i < 105; i++)
tasks.Add(client.GetAsync(uri));

Task.WaitAll(tasks.ToArray());

关于c# - 基于任务的并发比直接使用 System.Threading.Thread 慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31052757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com