Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
484 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...