.net 4.0 - In parallel call, limit executions per second -
using tpl / parallel.foreach there out-of-the-box way limit number of times method called per unit of time (i.e. no more 50 calls per second). different limiting number of threads. perhaps there's simple hack make work?
one solution make thread-safe version of following https://stackoverflow.com/a/7728872/356790
/// <summary> /// class limits number of requests (method calls, events fired, etc.) can occur in given unit of time. /// </summary> class requestlimiter { #region constructors /// <summary> /// initializes instance of requestlimiter class. /// </summary> /// <param name="maxrequests">the maximum number of requests can made in given unit of time.</param> /// <param name="timespan">the unit of time maximum number of requests limited to.</param> /// <exception cref="argumentexception">maxrequests <= 0</exception> /// <exception cref="argumentexception">timespan.totalmilliseconds <= 0</exception> public requestlimiter( int maxrequests , timespan timespan ) { // check parameters if ( maxrequests <= 0 ) { throw new argumentexception( "maxrequests <= 0" , "maxrequests" ); } if ( timespan.totalmilliseconds <= 0 ) { throw new argumentexception( "timespan.totalmilliseconds <= 0" , "timespan" ); } // initialize instance vars _maxrequests = maxrequests; _timespan = timespan; _requesttimes = new queue<datetime>( maxrequests ); // sleep 1/10th timespan _sleeptimeinms = convert.toint32( math.ceiling( timespan.totalmilliseconds / 10 ) ); } #endregion /// <summary> /// waits until request can made /// </summary> public void waituntilrequestcanbemade() { while ( !tryenqueuerequest() ) { thread.sleep( _sleeptimeinms ); } } #region private members private readonly queue<datetime> _requesttimes; private readonly object _requesttimeslock = new object(); private readonly int _maxrequests; private readonly timespan _timespan; private readonly int _sleeptimeinms; /// <summary> /// remove requests older _timespan /// </summary> private void synchronizequeue() { while ( ( _requesttimes.count > 0 ) && ( _requesttimes.peek().add( _timespan ) < datetime.now ) ) { _requesttimes.dequeue(); } } /// <summary> /// attempts enqueue request. /// </summary> /// <returns> /// returns true if request enqueued. false if not. /// </returns> private bool tryenqueuerequest() { lock ( _requesttimeslock ) { synchronizequeue(); if ( _requesttimes.count < _maxrequests ) { _requesttimes.enqueue( datetime.now ); return true; } return false; } } #endregion }
Comments
Post a Comment