如何在C#中随机枚举列表项?

usr*_*ΛΩΝ 2 c#

对于大专家,我有一个具有挑战性的问题.这在我的代码中还没有实际用法,但来自我刚才的想法.

如果我有IList<T>,我如何实现一个随机遍历列表并且可以同时由多个线程使用的枚举器?

举例来说,如果我有元素A,B,C,D,E,F和两个并发线程执行for-each名单上环与取得的ReaderLock(所以我相信没有人会碰列表从而导致异常),我想各自的周期返回,例如B,E,C,D,A,FE,B,D,C,A,F.

我需要这个的原因是因为我需要在List<SslStream>元素上放置锁以向客户端发送数据,因为SslStream不是线程安全的.随机挑选元素(但确保我选择它们)可以减少锁定冲突概率,并且可以提高I/O绑定操作性能.

请记住,即使我告诉你为什么我需要这样的调查员,我仍然喜欢挑战.可以有其他方法将相同的数据发送到多个客户端,但我的问题仍然是相同的:) :)

jas*_*son 5

像这样的东西(显然需要生产):

class RandomList<T> : IEnumerable<T> {
     private readonly IList<T> list;
     private readonly Random rg;
     private readonly object sync = new Object();
     public RandomList(IList<T> list) : this(list, new Random()) { }

     public RandomList(IList<T> list, Random rg) {
         Contract.Requires<ArgumentNullException>(list != null);
         Contract.Requires<ArgumentNullException>(rg != null);
         this.list = list;
         this.rg = rg;
     }

     public IEnumerator<T> GetEnumerator() {
         List<int> indexes;
         // Random.Next is not guaranteed to be thread-safe
         lock (sync) {
             indexes = Enumerable
                 .Range(0, this.list.Count)
                 .OrderBy(x => this.rg.Next())
                 .ToList();
         }
         foreach (var index in indexes) {
             yield return this.list[index];
         }
     }
}
      IEnumerator IEnumerable.GetEnumerator() {
          return GetEnumerator();
      }
}
Run Code Online (Sandbox Code Playgroud)