C#同步集合的最佳实践

时间:2016-05-08 19:52:12

标签: c# multithreading asynchronous

鉴于以下内容,最佳同步技术人员是什么

*请注意,这是一个示例模型,还有很多事情要发生。

共享资源是从2个地方更新的工具字典:

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

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

  • 旁注从字典中读取时我不关心数据集成。这意味着我不介意某个人在任何给定点接收来自字典的非更新值。我真的介意永远丢失的实际更新,因为我刚刚更换了正在更新的整个仪器。

问题:

1)任何人都可以想到一种更好的方法来同步乐器字典上的操作。

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

1 个答案:

答案 0 :(得分:1)

  

同步集合的最佳做法

我认为最佳做法是使用lock,除非您需要其他内容。

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

  

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

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

如果 使用基于Task的对象(例如,它是共享的),则实际上只需要WaitHandle - 包装器 - WaitHandle情况在进程之间)并希望使用异步代码来使用它。听起来不像这种情况适用于此。

  

旁注从字典中读取时我不关心数据集成。这意味着我不介意某个人在任何给定点接收来自字典的非更新值。

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

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