使用自定义 IEnumerator 时,C# 的 yield 返回线程是否安全?

问题描述

我有一个自定义 IEnumerator 类的简单概念,它提供结构/值类型的枚举。 (整数、日期时间、枚举等)

class MyNumer : IEnumerator<int>
{
   public MyNumer(int start,int end) { _start = start; _end = end; }
   int _start;
   int _end;

   //Please just assume i've implemented the rest of IEnumerator,this is the only element that is 
   //pertinent to the question

   public bool MoveNext()
   {
      if (this.Current == 0) this.Current = _start;
      else if (this.Current <= _end) this.Current++;
      return this.Current <= _end;
   }
}

class ThreadedClass
{
   public IEnumerable<int> GetNumbers(int start,int end)  //this method can be called from multiple threads
   {
      IEnumerator<int> numer = new MyNumer(start,end);
      while (numer.MoveNext()) yield return numer.Current;
   }
}

我关心的是提供了这个例子,如果:

  1. Thread1 调用“myThreadedClass.GetNumbers(1,10)”
  2. Thread2 调用“myThreadedClass.GetNumbers(30,40)”
  3. Thread3 调用“myThreadedClass.GetNumbers(70,100)”

我会得到三个独立的、不同的 IEnumerable 返回,还是线程会在“yield return”上发生冲突?

解决方法

不仅您将获得三个不同的 IEnumerable<int> 对象,而且每次您枚举它们中的每一个时,都会创建一个新的 IEnumerator<int>,它具有自己独特的 MyNumer 内部实例班级。因此,即使所有三个线程都共享同一个 IEnumerable<int> 实例(由 GetNumbers 方法的单次调用返回),也不会有线程安全问题。