C#同步集合的最佳实践

C#同步集合的最佳实践,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,鉴于以下情况,最好的同步技术人员是什么 *请注意,这是一个示例模型,还有更多的事情要做。 共享资源是仪器字典,它从两个地方更新: (1) 内部值正在快速更新 (2) 整个集合将刷新 public class Insturment { public Feed Feed{ get; set;} } static IDictionary<string,Instrument> instruments = new Dictionary<string,Ins

鉴于以下情况,最好的同步技术人员是什么

*请注意,这是一个示例模型,还有更多的事情要做。

共享资源是仪器字典,它从两个地方更新:

(1) 内部值正在快速更新

(2) 整个集合将刷新

  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);
        }     
   }
或者使用任何类型的任务包装器并等待它。 类似这样的构造:

  • 旁注:阅读字典时,我不关心数据的完整性。这意味着我不介意有人在任何给定点从字典接收未更新的值。我真的很介意实际更新永远丢失,因为我刚刚更换了正在更新的整个仪器
问题:

1) 有人能想出更好的方法来同步仪器字典上的操作吗

2) 在包装WaitHandle的任务上使用async/Wait有什么好处吗?(如上面链接中所述)

同步集合的最佳实践

我认为最好的做法是使用
lock
,除非您需要其他东西

例如,如果需要异步锁定,可以使用
SemaphoreSlim
asynchlock
实现之一

或者使用任何类型的任务包装器并等待它

我不会将该解决方案用于集合同步。如果需要异步兼容的同步,请使用异步兼容的同步原语(例如
SemaphoreSlim
AsyncLock
)。如果您不需要它,那么只需使用
lock

只有当您必须使用基于
WaitHandle
的对象(例如,它在进程之间共享)并希望使用异步代码时,才真正需要使用
Task
-wrapper-around-
WaitHandle
情况。听起来这种情况在这里并不适用

旁注:阅读字典时,我不关心数据的完整性。这意味着我不介意有人在任何给定点从字典接收未更新的值

无论如何,我建议锁定读取。如果不这样做,可能会出现各种各样的问题(比如撕裂)


作为旁注:您对场景的描述一直使用术语“更新”。听起来你可能更想要一个生产者/消费者解决方案,或者像Rx一样发布/订阅,而不是一个共享的同步集合。

使用ConcurrentDictionarylets说我是,请描述一下这对我有什么帮助。我很高兴你提起了这件事请注意,我正在替换Build()中的整个instrument对象,我不想在替换字典中的父对象时丢失新的提要。对不起,我误解了你的问题,忘了它:),除非你希望有来自不同来源的多个OnNewFeed,否则它不会帮助你,对不起,弄错了。
   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();     
   }