你如何限制每秒的操作次数?
你如何限制每秒的操作次数?
假设我们必须将文件从一个位置复制到另一个位置,并且我们不希望每秒处理超过5个文件。
请看看我在做什么
private static string currentStamp; private static int processedInCurrentStamp = 0; private static void Main(string[] args) { currentStamp = DateTime.Now.ToString("{0:d/M/yyyy HH:mm:ss}"); Run(); } private static void Run() { for (int i = 0; i < Int32.MaxValue; i++) { string s = DateTime.Now.ToString("{0:d/M/yyyy HH:mm:ss}"); if (currentStamp.Equals(s)) { if (processedInCurrentStamp < 5) { ProcessItem(); processedInCurrentStamp++; } } else { Console.WriteLine("{0} ::: {1}", currentStamp, processedInCurrentStamp); currentStamp = s; processedInCurrentStamp = 0; } } }
但我需要一种更优雅,更防弹的方式。
获取开始时间,然后在循环中计算应当处理到当前时间的最大文件数,并在您处于领先状态时进行hibernate:
DateTime start = DateTime.UtcNow; int i = 1; while (i <= 100) { int limit = (int)((DateTime.UtcNow - start).TotalSeconds * 5.0); if (i <= limit) { Console.WriteLine(i); i++; } else { Thread.Sleep(100); } }
这样,如果某些操作需要更长时间,代码将会赶上。 如果你一秒钟只进行三次操作,那么下一秒就可以进行七次操作。
请注意,我使用UtcNow
而不是Now
来避免每年发生两次的令人讨厌的跳跃。
编辑:
另一种方法是测量操作所花费的时间,并在其余的时间段内hibernate:
for (int i = 1; i <= 100; i++ ) { DateTime start = DateTime.UtcNow; Console.WriteLine(i); int left = (int)(start.AddSeconds(1.0 / 5.0) - DateTime.UtcNow).TotalMilliseconds; if (left > 0) { Thread.Sleep(left); } }
我会创建一个简单的方法,一次处理五个文件,并使用计时器每秒调用一次。
Sumee
您可以使用受限制的生产者/消费者队列。 它会有一个后台线程,它以一定的间隔运行,处理你的文件。 您可以在文件名到达时将其排队,并且受限制的出列操作(Action)将出列。 这是我的意思的一个例子:
public class ThrottledQueue : IDisposable where T : class { readonly object _locker = new object(); readonly List _workers; readonly Queue _taskQueue = new Queue (); readonly Action _dequeueAction; readonly TimeSpan _throttleTimespan; readonly Thread _workerThread; /// /// Initializes a new instance of the class. /// /// interval between throttled thread invokation /// The dequeue action. public ThrottledQueue(int millisecondInterval, Action dequeueAction) { _dequeueAction = dequeueAction; // Create and start a separate thread for each worker _workerThread = new Thread(Consume) { IsBackground = true, Name = string.Format("ThrottledQueue worker") }; _workerThread.Start(); _throttleTimespan = new TimeSpan(0,0,0,0,millisecondInterval); } /// /// Enqueues the task. /// /// The task. public void EnqueueTask(T task) { lock (_locker) { _taskQueue.Enqueue(task); } } /// /// Consumes this instance. /// void Consume() { while (true) { T item = default(T); lock (_locker) { Monitor.Wait(_locker, _throttleTimespan); if (_taskQueue.Count != 0) item = _taskQueue.Dequeue(); } if (item == null) return; // run actual method _dequeueAction(item); } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { // Enqueue one null task per worker to make each exit. EnqueueTask(null); _workerThread.Join(); } }
请注意,当您尝试将处理的项目数限制为每秒500个时,上面的代码仍会运行紧密循环,因此即使不处理文件也会对CPU造成负担。
如果你想要一个真正的限制,你必须将你的逻辑改为定时器或事件驱动,或者使用其中一个Wait *方法来空闲你的进程,同时等待下一次做一些工作的机会。
使用令牌桶:
https://en.wikipedia.org/wiki/Token_bucket
上述就是C#学习教程:你如何限制每秒的操作次数?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1031623.html