C#同步集合的最佳实践



给定以下内容,什么是最好的同步技术人员

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

共享资源是仪器词典,从两个位置更新:

(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);
        }     
   }

当使用手动重置事件重建整个集合时,我在UpdateFeed()上想到了相同的基本概念块线程。

   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();     
   }     

或者使用任何类型的任务包装器并等待它。类似这样的结构:Stephen Cleary 的anser

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

问题:

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

2) 在包裹WaitHandle的任务上使用async/await有什么好处吗?(就像上面链接中描述的那样)

同步集合的最佳实践

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

例如,如果您需要异步锁定,可以使用SemaphoreSlim或其中一个AsyncLock实现。

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

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

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

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

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

顺便说一句:你对场景的描述一直使用"更新"一词。听起来你可能想要更多的生产者/消费者解决方案,或者像Rx一样的发布/订阅,而不是共享、同步的集合。

最新更新