none
Thread safety RRS feed

  • Question

  • Hi!I have a need to use BufferBlock as a single data input point in multithreading environment.

    Can you suggest me, is Post method of  BufferBlock class thread-safe or not? As MSDN mentions all .NET library classes guarantee thread-safety only for static classes. Should i consider locking or some kind of thread-storage, ThreadLocal for example?



    Monday, May 21, 2012 5:11 PM

Answers

  • The Post method is by default thread-safe; it may be used on the same instance concurrently from multiple threads.  I say "by default" because for certain blocks, if you know you're only ever going to be posting to the blocks from one thread at a time, you can set DataflowBlockOptions.SingleProducerConstrained to true when you create that block; this tells the block that you won't be using Post concurrently, allowing the block to internally optimize for this case, but making Post not thread-safe.
    Monday, June 4, 2012 1:58 PM

All replies

  • I believe that methods like Post() are thread-safe, mostly because processing of each block and also inside one block can happen in parallel.

    If Post() was not thread-safe, and you created a dataflow like this:

                   TransformBlock
                  /              \
    BroadcastBlock                BufferBlock
                  \              /
                   TransformBlock
    

    Then it wouldn't work correctly, because processing in the two TransformBlocks can run in parallel. (Although TransformBlock won't actually use Post() internally, I don't see why the thread-safety would be any different.)

    But I agree that it's confusing that the documentation says that all instance methods are not guaranteed to be thread-safe. Also, to confuse matters even more, Post() isn't actually an instance method, it's an extension method.

    • Edited by svickMVP Monday, May 21, 2012 9:06 PM
    Monday, May 21, 2012 9:04 PM
  • I cannot rely just on an assumption. Probably i should see a code with Reflector or just use something like that:

    public static class TaskExecutor
    {
            public static ThreadLocal<BufferBlock<TaskBase>> buffer= new ThreadLocal<BufferBlock<TaskBase>>(()=>
                { 
                    var buff = new BufferBlock<TaskBase>(new DataflowBlockOptions(){MaxMessagesPerTask = DataflowBlockOptions.Unbounded});
                    buff.LinkTo(executor);
                    return buff;
                });             
            public static ActionBlock<TaskBase> executor=new ActionBlock<TaskBase>(()=>{});
    }
    Seems to be a good tradeoff for thread-safety.

    Tuesday, May 22, 2012 1:42 PM
  • The Post method is by default thread-safe; it may be used on the same instance concurrently from multiple threads.  I say "by default" because for certain blocks, if you know you're only ever going to be posting to the blocks from one thread at a time, you can set DataflowBlockOptions.SingleProducerConstrained to true when you create that block; this tells the block that you won't be using Post concurrently, allowing the block to internally optimize for this case, but making Post not thread-safe.
    Monday, June 4, 2012 1:58 PM
  • In web environment you do not have that luxury. There is a need for a set of none blocking concurrent collections as async code is the way forward
    Friday, June 29, 2018 10:39 AM