I am basically looking for a container of image collections acquired from camera in a thread. Since ConcurrentQueue is thread-safe, I wanted to use it. But while debugging my code, I found this article saying
If the elements are small, you’ll probably never notice this. If, however, the elements hold on to large resources (e.g. each element is a huge image bitmap), it’s possible you could see the impact of this (one workaround is to queue a wrapper object, e.g. have a
ConcurrentQueue<StrongBox<T>>
rather than aConcurrentQueue<T>
, and null out the wrapper’s reference to the T value after the wrapper has been dequeued).
As far as I can see, StrongBox
is a kind of wrapper for original value. Does that mean I have to store another collection of the images?
So I am looking for an usage or an example of ConcurrentQueue<StrongBox<T>>.
Only thing I found from google is this code.
The reminder of the dangers of premature optimization are in the comments, so I will address the semantics of what's going on here.
Like the article points out, the ConcurrentQueue
can hold on to references of some things that have already gone through it. I learned it as 'a few dozen' and the article says it is no more than 31, which seems to gel pretty nicely. If the queue is tracking big objects, like your 2000x2000 Bitmaps, that can theoretically become a problem. It depends on what the rest of your program is doing, of course.
Wrapping it in a StrongBox<T>
helps because the only thing StrongBox
does is hold onto a reference to something else. Therefore, a StrongBox
has a very tiny footprint, and whatever it holds will go out of scope and (theoretically) get GC'd quicker.
Since StrongBox
has all the content of diet soda, you're kind of overthinking its usage. You literally just load up the Value
field with some T
and then reference it later. It looks a little like this:
var boxedBitmap = new StrongBox<Bitmap>(new Bitmap(1,1));
var bitmap = boxedBitmap.Value;
Or alternatively:
var boxedBitmap = new StrongBox<Bitmap>();
boxedBitmap.Value = new Bitmap(1,1);
var bitmap = boxedBitmap.Value;
Seriously, the implementation of this class if you pop it open in Reflector is like 5 lines.
This being the case, your usage of ConcurrentQueue<T>
is not really any different from the usage of ConcurrentQueue<StrongBox<T>>
. You'll simply tack on .Value
before you send the resource to its destination thread. This did help a company I worked for reduce the memory imprint of a massive multithreaded analysis service by quite a bit by simply passing around a reference to a deterministic tool instead of passing the entire tool around, but your mileage may vary - I am not clear on what ramifications it would have if you were passing something to be mutated and then used by something else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With