我怎么能等到十个任务完成后再执行下一个任务呢?

本文关键字:任务 执行 下一个 十个 怎么能 | 更新日期: 2023-09-27 18:07:51

我正在访问一个web服务,它有请求限制,你可以每分钟做。我必须访问X> 10个条目,但我每分钟只允许制作10个。

我将服务实现为Singleton,它可以从代码的不同部分访问。现在我需要一种方法来知道,发出了多少请求,以及是否允许我发出一个新的请求。

因此,我编写了一个小示例代码,其中添加了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)));
        }
    }
}

我怎么能等到十个任务完成后再执行下一个任务呢?

一个很好的sempahor解决了我的问题。这是一个经典的线程问题,有一些经过测试的概念如何解决它,这是我正在使用的:

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();
        }
    }
}