-1

Given the following, what would be the best synchronization technician

* Please note that this an example model and there are much more things going on.

The shared resource is the instruments dictionary which is updated from 2 places:

(1) an inner value is being rapidly updated.

(2) the entire collection is refreshed.

  public class Insturment
  {
       public Feed Feed{ get; set;}
  }

  static IDictionary<string,Instrument> instruments = new Dictionary<string,Instrument>();

   // (1) This happens frequently  
   public void OnNewFeed(Feed feed)
   {
       instruments[feed.Symbol].Feed = feed;
   }

   // (2) happens every few hours ,or manually triggered at any given time 
   public void BuildInstruments()
   {
        foreach(var instrument in newInstruments)
        {
             instruments.AddOrUpdate(insturment.Symbol,insturment);
        }     
   }

I thought of the same basic concept block threads on UpdateFeed() when the entire collection is being rebuilt using a manual reset event.

   ManualResetEvent _mre = new ManualResetEvent(false);

   public void OnNewFeed(Feed feed)
   {
       _mre.WaitOne();
       instruments[feed.Symbol].Feed = feed;
   }

   public void BuildInstruments()
   {
        _mre.Reset();

        foreach(var instrument in newInstruments)
        {
             instruments.AddOrUpdate(insturment.Symbol,insturment);
        }

        _mre.Set();     
   }     

Or the same thing using any kind of Task wrapper and awaiting it. something like this construct : The anser by Stephen Cleary

  • Side note I don't care about data integraty when reading from the dictionary. meaning i don't mind some one receiving non-updated values from the dictionary at any given point. I do mind the actual update from being lost for ever because i just replaced the entire instrument that was being updated.

Questions :

1) Can any one think of a better approach to synchronize the operations on instruments dictionary.

2) Is there any advantages of using async/await on a task wrapping the WaitHandle ? ( like the one described in the link above)

Community
  • 1
  • 1
eran otzap
  • 12,293
  • 20
  • 84
  • 139
  • 2
    Use a ConcurrentDictionary – Gusman May 08 '16 at 19:59
  • lets say that i am please describe how that would aid me. and i'm glad you brought it up. :) please notice 2 things i'm replacing the entire instrument object in Build() and i don't want to loose the new Feed coming in while i replacing that parent object in the dictionary. – eran otzap May 08 '16 at 20:00
  • Sorry, I misunderstood your question, forget it :), unless you expect to have multiple OnNewFeed from different sources then it will not help you, sorry for the mistake. – Gusman May 08 '16 at 20:02

1 Answers1

1

Best practice for synchronizing a collection

I would say the best practice is to use lock unless you need something else.

E.g., if you need asynchronous locking, you can use SemaphoreSlim or one of the AsyncLock implementations.

Or the same thing using any kind of Task wrapper and awaiting it.

I would not use that solution for collection synchronization. If you need async-compatible synchronization, then use an async-compatible synchronization primitive (such as SemaphoreSlim or AsyncLock). And if you don't need it, then just use lock.

The Task-wrapper-around-WaitHandle situation is really only needed if you have to use a WaitHandle-based object (e.g., it's shared between processes) and want to consume it with asynchronous code. It doesn't sound like that scenario applies here.

Side note I don't care about data integraty when reading from the dictionary. meaning i don't mind some one receiving non-updated values from the dictionary at any given point.

I do recommend locking on reads anyway. There's a variety of problems (like tearing) that can occur if you don't.

Just as a side note: your description of your scenario keeps using the term "update". It sounds like you may want more of a producer/consumer solution, or possibly a publish/subscribe like Rx, rather than a shared, synchronized collection.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810