Is foreach the only way to use BlockingCollection <T> in C #?

Now I am starting to work with TPL. I saw a simple version of the producer / consumer model using TPL in this video .

Here is the problem:

The following code:

BlockingCollection<Double> bc = new BlockingCollection<Double>(100); IEnumerable<Double> d = bc.GetConsumingEnumerable(); 

returns an IEnumerable<Double> , which can be iterated (and automatically consumed) using foreach:

 foreach (var item in d) { // do anything with item // in the end of this foreach, // will there be any items left in d or bc? Why? } 

My questions:

  • If I get IEnumerator<Double> dEnum = d.GetEnumerator() from d (e.g. to iterate over d with a while ), will the d.MoveNext() list be used? (My answer: I don’t think so, because dEnum not related to d if you know what I mean. Thus, it consumes dEnum , but not d , and even bc )
  • Is it possible to execute the bc (or d ) loop differently than the foreach , consuming elements? (the while much faster than the foreach , and I am concerned about performance issues for scientific computing problems).
  • What exactly does the average in the BlockingCollection<T> type consume?

For example, the code:

 IEnumerator<Double> dEnum = d.GetEnumerator(); while (dEnum.MoveNext()) { // do the same with dEnum.Current as // I would with item in the foreach above... } 

Thank you all in advance!

+4
source share
2 answers

If I get IEnumerator<Double> dEnum = d.GetEnumerator() from d (e.g. to iterate over d with a while loop), will d.MoveNext () also use a list?

That's right. That's all the foreach will do anyway.

Can I skip through bc (or d) differently than a foreach loop, consuming elements? (the while loop is much faster than the foreach loop, and I am concerned about performance issues for scientific computing issues)

If your while is faster, it means that you are doing something wrong. They should be exactly the same, except that the foreach will also remove the iterator, which you should do ...

If you can publish a short but complete program demonstrating this discrepancy, we can examine it in more detail.

An alternative is to use Take (and similar methods).

What exactly does the average in the BlockingCollection class consume?

"Effectively remove the next item from the collection."

+4
source

No performance issues with foreach . Using an enumerator directly will not give you any measurable performance improvement over just using a foreach .

At the same time, GetConsumingEnumerable() returns the standard IEnumerable<T> , so you can list it in any way. Getting IEnumerator<T> and listing through it directly will work the same.

Note that if you do not want to use GetConsumingEnumerable() , you can simply use ConcurrentQueue<T> . By default, a BlockingCollection<T> wraps a ConcurrentQueue<T> and actually just provides a simpler API ( GetConsumingEnumerable() ) to make it easier to write Producer / Consumer scripts. Using ConcurrentQueue<T> will directly be closer to using BlockingCollection<T> without using an enumeration.

+4
source

Source: https://habr.com/ru/post/1438068/


All Articles