繁体   English   中英

暂停 Parallel.Foreach 循环

[英]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 实例。

在任务内部 - 在一个永远循环中(带有取消中止条件):

  • 进入锁,在里面做:
    • 检查队列中的下一个条目以出列,如果超过 1 分钟删除
    • 做到以上点,直到没有人超过 1 分钟
    • 如果还有超过 220 个条目
      • 在这个任务中等待,直到时间过去,直到下一个队列条目过去 - 所以计算等待时间并等待
      • 删除队列条目(现在 1 是空闲的 - 用于此任务)
    • 将当前时间戳添加/排队到队列中
  • 离开锁
  • 拨打 API 电话

--> 所以带锁的整个代码可以放在一个方法中并从任务中调用

我是否理解正确,从 UTC 0.000 秒开始,您在任何 60 秒或每绝对分钟内不应超过 225 个请求?

PS:我有一个类似的问题,但被锁定在当地时区的一天 - 例如 Instagram 只允许在当地时区一天 24 小时内发布 100 张照片:所以从 22:00 到 02,00 下一个早上仍然可以发布200张照片。 如果这两天都没有其他人发布。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM