2014-06-08 29 views
1

我正在訪問一個Web服務,它具有請求限制,您可以每分鐘完成一次。我必須訪問X> 10個條目,但只允許每分鐘製作10個條目。我該如何等待十個任務完成,然後執行接下來的十個任務

我意識到服務是一個單例,它可以從代碼的不同部分訪問。現在我需要一種方法來了解,提出了多少請求以及是否允許我創建一個新的請求。

因此我做了一個小小的示例代碼,它增加了100個任務。每個任務的延遲時間爲3秒,並且Task只能在未使用Task.WhenAny之前執行10個任務時執行。但是,當我從列表中刪除完成的任務時,我收到了一個「An exception of type 'System.InvalidOperationException' occurred in mscorlib.dll but was not handled in user code」異常。

我該如何解決這個問題?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 
{ 
    class Test 
    { 
     private static Test instance; 
     public static Test Instance 
     { 
      get 
      { 
       if (instance == null) 
       { 
        instance = new Test(); 
       } 
       return instance; 
      } 
     } 


     private List<Task> taskPool = new List<Task>(); 
     private Test() 
     { 

     } 

     public async void AddTask(int count) 
     { 
      // wait till less then then tasks are in the list 
      while (taskPool.Count >= 10) 
      { 
       var completedTask = await Task.WhenAny(taskPool); 
       taskPool.Remove(completedTask); 
      } 

      Console.WriteLine("{0}, {1}", count, DateTime.Now); 

      taskPool.Add(Task.Delay(TimeSpan.FromSeconds(3))); 
     } 
    } 
} 
+0

你能告訴我們stacktrace嗎? –

+0

你的意思是調用堆棧。那麼它是相當不起眼的 – Stefan

+0

不,我的意思是堆棧跟蹤異常 –

回答

2

一個很好的舊Sempahore解決了我的問題。這是一個典型的線程問題,有幾個測試概念如何解決它,這是我正在使用的一個:

using System; 
using System.Collections.Concurrent; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 
{ 
    class Test 
    { 
     private static Test instance; 
     public static Test Instance 
     { 
      get 
      { 
       if (instance == null) 
       { 
        instance = new Test(); 
       } 
       return instance; 
      } 
     } 

     private static Semaphore _pool = new Semaphore(0, 10); 
     private Test() 
     { 
      _pool.Release(10); 
     } 

     public async void AddTask(int count) 
     { 
      _pool.WaitOne(); 
      var task = Task.Delay(TimeSpan.FromSeconds(3)); 
      Console.WriteLine("{0}, {1}", count, DateTime.Now); 
      await task; 
      _pool.Release(); 
     } 
    } 
}