Naw*_*waz 5 c# ienumerable multithreading iqueryable
关于如何在多线程应用程序中共享IEnumerable和IQueryable访问,我几乎没有疑问.
请考虑此代码段.
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().
这取决于实施.一些实现IEnumerable<T>也实现IEnumerator<T>,并从中返回GetEnumerator().在这种情况下,它显然不是线程安全的......
至于IQueryable<T>,它还取决于实施.例如,Entity Framework上下文不是线程安全的,只能在创建它们的线程上正常工作.
所以这个问题没有独特的答案......它可能适用于某些实现,而不适用于其他实现.