Recently I need to get balance getting resources from a restricted number of sources. So, for example...
I am getting resource R, and I have factories A, B and C creating those Rs. Each of those factories has a very limited capacity for creating those resources, and can only create two Rs at a time. It is easy to put the factories behind a semaphore and limit how many threads can be requesting resources from each factory at a time.
The challenge is evenly balancing the workload between all three factories. Also, please note that you can't just round robin the semaphores because there is no way to ensure that each operation will complete in the same amount of time.
To do this I created a generic IResourceLoader interface, and made two implementations: one to wrap a semaphore, and the other to wrap and balance a collection of IResourceLoaders. Below is the implementation, complete with unit tests; let's take a look!
Interface
public interface IResourceLoader<T>
{
int Available { get; }
int Count { get; }
int MaxConcurrency { get; }
Task<T> GetAsync(CancellationToken cancelToken = default(CancellationToken));
bool TryGet(out Task<T> resource, CancellationToken cancelToken = default(CancellationToken));
}