【发布时间】:2016-10-14 14:04:00
【问题描述】:
我正在努力改进我的一些代码以提高效率。在原始代码中,我将允许的线程数限制为 5,如果我已经有 5 个活动线程,我会等到一个完成后再开始另一个。现在我想修改此代码以允许任意数量的线程,但我希望能够确保每秒只有 5 个线程启动。例如:
- 第二个 0 - 5 个新线程
- 第二个1-5个新线程
- 第二个 2 - 5 个新线程 ...
原始代码(cleanseDictionary 通常包含数千个项目):
ConcurrentDictionary<long, APIResponse> cleanseDictionary = new ConcurrentDictionary<long, APIResponse>();
ConcurrentBag<int> itemsinsec = new ConcurrentBag<int>();
ConcurrentDictionary<long, string> resourceDictionary = new ConcurrentDictionary<long, string>();
DateTime start = DateTime.Now;
Parallel.ForEach(resourceDictionary, new ParallelOptions { MaxDegreeOfParallelism = 5 }, row =>
{
lock (itemsinsec)
{
ThrottleAPIRequests(itemsinsec, start);
itemsinsec.Add(1);
}
cleanseDictionary.TryAdd(row.Key, _helper.MakeAPIRequest(string.Format("/endpoint?{0}", row.Value)));
});
private static void ThrottleAPIRequests(ConcurrentBag<int> itemsinsec, DateTime start)
{
if ((start - DateTime.Now).Milliseconds < 10001 && itemsinsec.Count > 4)
{
System.Threading.Thread.Sleep(1000 - (start - DateTime.Now).Milliseconds);
start = DateTime.Now;
itemsinsec = new ConcurrentBag<int>();
}
}
我的第一个想法是将MaxDegreeofParallelism 增加到更高的值,然后有一个辅助方法,该方法将在一秒钟内仅限制 5 个线程,但我不确定这是否是最好的方法,是否是,我可能需要一个lock 在这一步附近?
提前致谢!
编辑 我实际上正在寻找一种限制 API 请求而不是实际线程的方法。我以为他们是同一个。
编辑 2:我的要求是每秒发送超过 5 个 API 请求
【问题讨论】:
-
Parallel.ForEach不会启动新线程。它使用许多任务对大量数据进行分区,并让每个任务专门处理该数据。你想用这段代码做什么?当你最多有 5 个并发调用时,为什么你试图“节流”? -
@PanagiotisKanavos 这是主机设置的要求,在任何给定的秒内只允许 5 个(所以我想)但现在我发现他们的计数器在每一秒过去后都会重置。跨度>
-
您似乎正在尝试限制 请求,而不是线程。您的实际要求是什么?执行例如最多 5 个并发请求,或 5 个请求/秒?
-
@PanagiotisKanavos 是的,我想这更清楚——我想限制请求,以便每秒只有 5 个请求。我确实希望尽可能多地发出请求
-
唯一允许对这个问题投反对票的是那些过去必须实施请求限制的人!如果您不了解这些技术,只有他们知道这是多么令人困惑!
标签: c# multithreading parallel.foreach