BlockingCollection<T> 中的 IsCompleted 属性 是否真的阻塞了?
Does the IsCompleted property in the BlockingCollection<T> actually block?
我正在尝试为我从控制器异步读取的数据流实施 producer/consumer 模式。为此,我想使用 BlockingCollection<T>
,但要确保获得所需的结果。我的消费者看起来像这样:
// make sure there is actually some data in the buffer
if (!this.buffer.IsCompleted)
{
// attempt to read from the buffer
data = this.buffer.Take();
// construct the message object
message = this.ConvertToMessageObject(data);
}
IsCompleted
属性 真的会阻塞吗?因此,如果另一个线程要访问缓冲区,我希望它在调用 Take
方法之前等待并确保缓冲区实际上不是 "completed"。
在我的应用程序中,期望的效果是允许我避免在缓冲区实际上为空时构造新的消息对象。所以这就是为什么我在尝试 Take
.
之前检查 IsCompleted
此外...我了解到 Take
方法不再阻塞一次 IsAddingCompleted = true
。所以我不希望消费者从无效的 Take
方法中获取数据,它别无选择(如果消费者不知道完成状态)。我想我真的很难解释我在这里担心的事情......
Does the IsCompleted
property actually block?
不,它会立即return。
So that if another thread was going to access the buffer, I would like it to wait and make sure that the buffer is actually not "completed" before calling on the Take method.
这样做。当然,如果调用 IsCompleted
时缓冲区未完成,它将 return false
。它可能 在 具有 return 那个值之后完成,并且在您调用 IsCompleted
.[=20 时队列中可能没有任何项目=]
In my application, the desired effect would be to allow me to avoid constructing a new message object when the buffer is in fact empty.
Take
如果集合被阻塞并且其中没有任何项目,则会抛出异常,因此您无需担心。它不会永远阻塞,也不会在没有任何实际数据的情况下构造新消息。您可以在循环外捕获异常以在完成后继续。
综上所述,让 BlockingCollection
为您处理迭代要容易得多,而不是尝试构建您自己的消费迭代器(即使它不是 很难自己做)。你可以只写:
foreach(var data in buffer.GetConsumingEnumerable())
//...
它将消耗序列中的项目,直到缓冲区完成,然后在缓冲区中没有并且永远不会有任何项目时跳出循环。
我正在尝试为我从控制器异步读取的数据流实施 producer/consumer 模式。为此,我想使用 BlockingCollection<T>
,但要确保获得所需的结果。我的消费者看起来像这样:
// make sure there is actually some data in the buffer
if (!this.buffer.IsCompleted)
{
// attempt to read from the buffer
data = this.buffer.Take();
// construct the message object
message = this.ConvertToMessageObject(data);
}
IsCompleted
属性 真的会阻塞吗?因此,如果另一个线程要访问缓冲区,我希望它在调用 Take
方法之前等待并确保缓冲区实际上不是 "completed"。
在我的应用程序中,期望的效果是允许我避免在缓冲区实际上为空时构造新的消息对象。所以这就是为什么我在尝试 Take
.
IsCompleted
此外...我了解到 Take
方法不再阻塞一次 IsAddingCompleted = true
。所以我不希望消费者从无效的 Take
方法中获取数据,它别无选择(如果消费者不知道完成状态)。我想我真的很难解释我在这里担心的事情......
Does the
IsCompleted
property actually block?
不,它会立即return。
So that if another thread was going to access the buffer, I would like it to wait and make sure that the buffer is actually not "completed" before calling on the Take method.
这样做。当然,如果调用 IsCompleted
时缓冲区未完成,它将 return false
。它可能 在 具有 return 那个值之后完成,并且在您调用 IsCompleted
.[=20 时队列中可能没有任何项目=]
In my application, the desired effect would be to allow me to avoid constructing a new message object when the buffer is in fact empty.
Take
如果集合被阻塞并且其中没有任何项目,则会抛出异常,因此您无需担心。它不会永远阻塞,也不会在没有任何实际数据的情况下构造新消息。您可以在循环外捕获异常以在完成后继续。
综上所述,让 BlockingCollection
为您处理迭代要容易得多,而不是尝试构建您自己的消费迭代器(即使它不是 很难自己做)。你可以只写:
foreach(var data in buffer.GetConsumingEnumerable())
//...
它将消耗序列中的项目,直到缓冲区完成,然后在缓冲区中没有并且永远不会有任何项目时跳出循环。