首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >暂停Parallel.Foreach循环

暂停Parallel.Foreach循环
EN

Stack Overflow用户
提问于 2020-06-04 05:33:49
回答 2查看 251关注 0票数 0

我正在运行一个parallel.foreach循环来遍历一个列表。每个列表项都包含一个api的标识符,我在循环中访问它。

我正在访问的api每分钟最多可以有225个请求,所以我想在220个项目之后暂停循环的执行,并在整个分钟过去后再次恢复它们。我尝试使用Thread.sleep(numMilliSeconds),但它似乎为每个进入睡眠或类似性质的线程启动了一个新线程。

这就是我现在使用的大致内容:

代码语言:javascript
复制
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不是解决这个问题的正确方法,但是有没有类似的构造可以在Parallel.Foreach循环中使用呢?

EN

回答 2

Stack Overflow用户

发布于 2020-06-04 06:17:40

我选择了批量解决方案。感谢你的建议,@Algef Almocera

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2020-06-04 06:40:54

如果达到每分钟220个请求,您希望停止/暂停每个任务。这样他们每个人都可以到达它。所以每一个都应该检查它。如果发生这种情况,所有的任务都应该等待,直到有人释放它们。

因此,我将有一个队列来存储最后(0...220)个API调用的时间戳。和一个锁对象实例。

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

  • 进入锁,并在内部执行:
    • 检查队列中要出队的下一个条目,如果超过1分钟则删除
    • 以上直到没有超过1分钟的条目
    • 如果仍超过220个条目<代码>H19在此任务中等待,直到经过下一个队列条目-因此计算等待时间并等待
      • 删除队列条目(现在1是空闲的-对于此code

代码语言:javascript
复制
- add/enqueue the current timestamp to the queue

  • lock the lock
  • make the API call

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

我没理解错吧,从UTC 0.000开始,在任何60秒或每分钟绝对时间内,您不应该超过225个请求?

PS:我也有类似的问题,但它被锁定在当地时区的一天-例如,Instagram只允许在当地时区的一天24小时内发布100张照片!所以从22:00到第二天凌晨2:00仍然可以发布200张图片,如果这两天没有其他图片发布的话。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62183081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档