If you don't want to increase the size of your pool and assuming you are correctly returning each SocketAsyncEventArgs
after use you can use a BlockingCollection to hold the required number of SocketAsyncEventArgs
. The consumers will block when there are no more items to consume until an item is returned to the collection.
Update
Here is some sample code that creates a BlockingCollection
of size 1 and fires off some consumers to process simultaneously. Each consumer takes an item from the collection to process it and in the mean time the others are blocked on Take
until an item is added back to the collection.
When processing, you'll probably need to do that in a try/finally
block to ensure the item is always added back after processing it if an exception gets thrown.
To close the collection you call CompleteAdding()
and any blocked Take
methods will throw a InvalidOperationException
public void RunConsumer(BlockingCollection<SocketAsyncEventArgs> collection, int consumerId)
{
Task.Run( async () =>
{
Console.WriteLine("Consumer {0} waiting", consumerId);
SocketAsyncEventArgs args = null;
try
{
args = collection.Take();
Console.WriteLine("Consumer {0} processing", consumerId);
await Task.Delay(5000);
}
catch(ObjectDisposedException)
{
Console.WriteLine("Consumer {0} collection has been disposed", consumerId);
}
catch(InvalidOperationException)
{
Console.WriteLine("Consumer {0} collection has been closed", consumerId);
}
finally
{
// add the item back if collection hasn't been closed.
if(args != null && !collection.IsAddingCompleted)
collection.Add(args);
}
Console.WriteLine("Consumer {0} finished", consumerId);
});
}
Usage
void Main()
{
var collection = new BlockingCollection<SocketAsyncEventArgs>(1) { new SocketAsyncEventArgs() };
RunConsumer(collection, 1);
RunConsumer(collection, 2);
RunConsumer(collection, 3);
Thread.Sleep(9000);
collection.CompleteAdding();
Console.ReadLine();
}
Output
Consumer 1 waiting
Consumer 3 waiting
Consumer 2 waiting
Consumer 1 processing
Consumer 1 finished
Consumer 3 processing
Consumer 2 collection has been closed
Consumer 2 finished
Consumer 3 finished