如果你不想增加你的池的大小,並假設你正確地返回每個SocketAsyncEventArgs
使用後,您可以使用一個BlockingCollection來保存所需數量的SocketAsyncEventArgs
。當物品返回到收藏時,消費者會阻止沒有更多物品需要消費。
更新
下面是創建大小1和火災的BlockingCollection
關閉一些消費者能夠同時處理一些示例代碼。每個消費者從集合中取出一個物品進行處理,同時其他人在Take
上被封鎖,直到物品被添加回集合。
處理時,您可能需要在try/finally
塊中執行此操作,以確保在處理該項目後,如果拋出異常,則始終會重新添加該項目。
要關閉呼叫CompleteAdding()
和收集任何遮擋Take
方法將拋出一個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);
});
}
使用
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();
}
輸出
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
所以你很樂意等到SocketAsyncEventArgs變得可用? –
我試過了!我編輯了SocketAsyncEventArgsPool類的Pop()函數: – user2964559