在多线程应用程序中共享IEnumerable <T>和IQueryable <T>

Naw*_*waz 5 c# ienumerable multithreading iqueryable

关于如何在多线程应用程序中共享IEnumerableIQueryable访问,我几乎没有疑问.

请考虑此代码段.

ObservableCollection<SessionFile> files = /* some code */
IEnumerable<Pattern> allFilePatterns= /*some query */

foreach (Pattern pattern in allFilePatterns)
{
   string iclFilePath = Path.Combine(pattern.Location, pattern.Filename);
   SessionFile sfile = new SessionFile(iclFilePath, pattern.AnalysisDate);

   SomeDelegate invoker = new SomeDelegate(sfile.SomeHandler);
   invoker.BeginInvoke(allFilePatterns, null, null);

   files.Add(sfile );
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我正在使用BeginInvoke()相同的实例传递allFilePatterns给每个调用的处理程序sfile.SomeHandler.

假设在SomeHandler,我在循环中迭代allFilePatternsforeach,如下所示:

void SomeHandler(IEnumerable<Pattern> allFilePatterns)
{
    foreach(Pattern pattern in allFilePatterns)
    {
          //some code
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我的疑问是:既然BeginInvoke()是异步的,这意味着所有foreach在所有SomeHandler的所有文件会(在自己的线程每个)并行执行,会的共享实例IEnumerable如预期枚举/正常吗?这是一种正确的方法吗?我可以在多个线程中共享相同的实例IEnumerable,并且并行枚举它吗?

如果我使用IQueryable而不是IEnumerable上面的代码怎么办?我应该注意哪些副作用?

如果它不是线程安全的,那么我应该使用什么?

请注意,我正在使用IQueryable数据库查询,因为我不想从数据库中提取所有数据.因此,我想尽可能避免IQueryable.ToList().

Tho*_*que 5

这取决于实施.一些实现IEnumerable<T>也实现IEnumerator<T>,并从中返回GetEnumerator().在这种情况下,它显然不是线程安全的......

至于IQueryable<T>,它还取决于实施.例如,Entity Framework上下文不是线程安全的,只能在创建它们的线程上正常工作.

所以这个问题没有独特的答案......它可能适用于某些实现,而不适用于其他实现.