我正在使用BlockingCollection
來實現生產者/消費者模式。我有一個異步循環,用要處理的數據填充集合,然後在稍後時間由客戶端訪問。數據包到達稀疏,我希望輪詢在不使用阻塞呼叫的情況下完成。異步取消阻止收集
實質上,我正在尋找類似BeginTake
和EndTake
的東西,它不存在於阻塞集合中,以便我可以在回調中使用內部線程池。無論如何,它不一定是BlockingCollection
。任何我需要的東西都會很棒。
這就是我現在得到的。 _bufferedPackets
是BlockingCollection<byte[]>
:
public byte[] Read(int timeout)
{
byte[] result;
if (_bufferedPackets.IsCompleted)
{
throw new Exception("Out of packets");
}
_bufferedPackets.TryTake(out result, timeout);
return result;
}
我想這是這樣的,在僞代碼:
public void Read(int timeout)
{
_bufferedPackets.BeginTake(result =>
{
var bytes = _bufferedPackets.EndTake(result);
// Process the bytes, or the resuting timeout
}, timeout, _bufferedPackets);
}
什麼是我對這個選擇?我不希望任何線程處於等待狀態,因爲有很多其他IO東西要處理,並且我會很快耗盡線程。
更新:我已經重寫有問題的代碼,以不同的方式使用異步過程,實質上交換基礎上的回調,如果有超時限制內等待請求。這工作正常,但如果有一種方法可以做到這一點,而不依賴於定時器並交換周圍可能導致競爭條件且很難寫入(並理解)的lambda的方法,它仍然會很棒。我已經用自己的異步隊列實現解決了這個問題,但如果有更標準和經過充分測試的選項,它仍然非常棒。
目前,我認爲沒有任何TPL集合提供除了ObservableCollection之外的異步方法。你怎麼看 ? – 2012-08-14 10:12:21
你可以把它包裝在一個任務中,任務= Task.Factory.StartNew(()=> {//你的代碼返回字節[]});'但是這不是智慧,並且必須有更好的方法。 –
MoonKnight
2012-08-14 10:16:32
包裝在任務中將消耗一個將被鎖定在等待句柄中的任務。由於有很多任務正在進行,這將永遠佔用一項任務,這將使我不幸地在游泳池中耗盡任務。 – Dervall 2012-08-14 11:01:37