我正在使用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