[英]Pausing a Parallel.Foreach loop
我正在运行一个 parallel.foreach 循环来遍历一个列表。 每个列表项都包含一个 api 的标识符,我在循环中访问它。
我正在访问的 api 每分钟最多有 225 个请求,所以我想在 220 个项目后暂停执行循环,并在整整一分钟后再次恢复它们。 我尝试使用 Thread.sleep(numMilliSeconds),但它似乎为每个进入睡眠状态或类似性质的东西启动了一个新线程。
这大致是我现在正在使用的:
Parallel.ForEach(list, (currentItem) =>{
while(numRequestsLastMinute > 220 && DateTime.Now.Minute == lastDownloadTime.Minute)
{
var timeToPause = (60 - DateTime.Now.Second) * 1000;
Console.WriteLine("Thread pausing for" + timeToPause/100 + "seconds...");
Thread.Sleep(timeToPause);
Console.WriteLine("Thread resuming...");
}
if(DateTime.Now.Minute > lastDownloadTime.Minute)
{
lastDownloadTime = DateTime.Now;
numRequestsLastMinute = 0;
}
//send requests
}
显然,Thread.Sleep 不是 go 的正确方法,但是我可以在 Parallel.Foreach 循环中使用类似的构造吗?
我选择了批处理解决方案。 感谢您的提示,@Algef Almocera
int maxPerMinute = 220
while (list.Count > 0)
{
_ = Parallel.ForEach(batch, (currentItem) =>
{
});
batch = list.Take(maxPerMinute);
list = list.Skip(maxPerMinute).ToList();
Console.WriteLine(numItemsDone + " items downloaded");
if (DateTime.Now.Minute == lastDownloadTime.Minute)
{
var timeToPause = (60 - DateTime.Now.Second) * 1000;
Console.WriteLine(DateTime.Now.ToLongTimeString() + ": Thread pausing for " + timeToPause / 1000 + "seconds...");
Thread.Sleep(timeToPause);
Console.WriteLine(DateTime.Now.ToLongTimeString() + ": Thread resuming...");
}
lastDownloadTime = DateTime.Now;
}//end while
如果达到每分钟 220 个请求,您想要停止/暂停每个任务。 所以他们每个人都可以达到它。 所以每个人都应该检查它。 如果发生这种情况,所有任务都应该等到有人释放它们。
所以我会有一个队列来记录最后一次 (0...220) API 调用的时间戳。 和一个锁 object 实例。
在任务内部 - 在一个永远循环中(带有取消中止条件):
--> 所以带锁的整个代码可以放在一个方法中并从任务中调用
我是否理解正确,从 UTC 0.000 秒开始,您在任何 60 秒或每绝对分钟内不应超过 225 个请求?
PS:我有一个类似的问题,但被锁定在当地时区的一天 - 例如 Instagram 只允许在当地时区一天 24 小时内发布 100 张照片:所以从 22:00 到 02,00 下一个早上仍然可以发布200张照片。 如果这两天都没有其他人发布。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.