簡體   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