Limit the number of Tasks in Task.Factory.Start by second

坚强是说给别人听的谎言 提交于 2020-01-09 08:10:10

问题


I've seen a number of posts about limiting the number of tasks at a time (System.Threading.Tasks - Limit the number of concurrent Tasks is a good one).

However, I need to limit the number of tasks by second - only X number of tasks per second? Is there an easy way to accomplish this?

I thought about creating a ConcurrentDictionary, the key being the current second, and the second being the count so far. The doing a check if we are at 20 for the current second, then stop. This seems suboptimal.

I'd rather do something like spin up a task every 1s/20. Any thoughts?


回答1:


I think, this can be a starting point. Below sample creates 50 Tasks (running 5 tasks/sec).

This doesn't block the code that creates the tasks. If you want to block the caller until all task have been scheduled, then you can use Task.Delay((int)shouldWait).Wait() in QueueTask

TaskFactory taskFactory = new TaskFactory(new TimeLimitedTaskScheduler(5));

for (int i = 0; i < 50; i++)
{
    var x = taskFactory.StartNew<int>(() => DateTime.Now.Second)
                        .ContinueWith(t => Console.WriteLine(t.Result));
}

Console.WriteLine("End of Loop");

public class TimeLimitedTaskScheduler : TaskScheduler
{
    int _TaskCount = 0;
    Stopwatch _Sw = null;
    int _MaxTasksPerSecond;

    public TimeLimitedTaskScheduler(int maxTasksPerSecond)
    {
        _MaxTasksPerSecond = maxTasksPerSecond;
    }

    protected override void QueueTask(Task task)
    {
        if (_TaskCount == 0) _Sw = Stopwatch.StartNew();

        var shouldWait = (1000 / _MaxTasksPerSecond) * _TaskCount - _Sw.ElapsedMilliseconds;

        if (shouldWait < 0)
        {
            shouldWait = _TaskCount = 0;
            _Sw.Restart();
        }

        Task.Delay((int)shouldWait)
            .ContinueWith(t => ThreadPool.QueueUserWorkItem((_) => base.TryExecuteTask(task)));

        _TaskCount++;
    }

    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        return base.TryExecuteTask(task);
    }

    protected override IEnumerable<Task> GetScheduledTasks()
    {
        throw new NotImplementedException();
    }


}


来源:https://stackoverflow.com/questions/18771524/limit-the-number-of-tasks-in-task-factory-start-by-second

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!