2014-06-08 30 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(); 
     } 
    } 
}