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

发布于 2024-11-01 08:42:11 字数 1488 浏览 1 评论 0原文

我对如何在多线程应用程序中访问共享的 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 );
}

如您所见,我使用 BeginInvoke()相同实例 allFilePatterns 传递给每个名为 sfile.SomeHandler 的处理程序代码>.

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

void SomeHandler(IEnumerable<Pattern> allFilePatterns)
{
    foreach(Pattern pattern in allFilePatterns)
    {
          //some code
    }
}

现在我的疑问是:因为 BeginInvoke() 是异步的,这意味着所有文件的所有 SomeHandler 中的所有 foreach 都将并行执行(每个都在自己的线程中),的共享实例将并行执行>IEnumerable按预期/正常枚举?这是正确的做法吗?我可以在多个线程中共享 IEnumerable相同实例,并并行枚举它吗?

如果我在上面的代码中使用 IQueryable 而不是 IEnumerable 会怎么样?我应该注意什么副作用?

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

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

I've few doubts regarding how shared IEnumerable and IQueryable is accessed in multi-threaded application.

Consider this code snippet.

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

As you can see, I'm using BeginInvoke() passing the same instance allFilePatterns to each handler called sfile.SomeHandler.

Suppose in SomeHandler, I iterate allFilePatterns in a foreach loop, something like this:

void SomeHandler(IEnumerable<Pattern> allFilePatterns)
{
    foreach(Pattern pattern in allFilePatterns)
    {
          //some code
    }
}

Now my doubt is that: since BeginInvoke() is asynchronous, that means all foreach in all SomeHandler of all the files would execute parallelly (each in its own thread), would the shared instance of IEnumerable enumerate as expected/normal? Is this a right approach? Can I share same instance of IEnumerable in multiple threads, and enumerate it parallelly?

And what if I use IQueryable instead of IEnumerable in the above code? Any side-effect that I should be aware of?

If its not thread-safe, then what should I use?

Please note that I'm using IQueryable for database queries, as I don't want to pull all the data from database. Therefore, I want to avoid IQueryable.ToList() as much as possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小矜持 2024-11-08 08:42:11

这取决于实施。 IEnumerable 的某些实现还实现 IEnumerator,并从 GetEnumerator() 返回自身。在这种情况下,它显然不是线程安全的...

至于IQueryable,它也取决于实现。例如,实体框架上下文不是线程安全的,只能在创建它们的线程上正常工作。

所以这个问题没有唯一的答案......它可能适用于某些实现,但不适用于其他实现。

It depends on the implementation. Some implementations of IEnumerable<T> also implement IEnumerator<T>, and return themselves from GetEnumerator(). In that case it's obviously not thread-safe...

As for IQueryable<T>, it also depends on the implementation. For instance, Entity Framework contexts are not thread-safe, and will only work properly on the thread that created them.

So there is no unique answer to that question... it will probably work for some implementations, and not for others.

瑾兮 2024-11-08 08:42:11

当作为参数传递给委托时,我会 ToList() 你的枚举,以实际创建一个新的集合供线程使用并避免问题。

但是,我想知道为什么您需要将可枚举的每个元素枚举 N 次(实际上是 N^2)?这听起来效率很低。

编辑:根据我的意图更新

I would ToList() your enumerable when passing as an argument to the delegate to actually create a new set for the thread to work with and avoid problems.

However, I'm wondering why you would need to have each element of the enumerable enumerated N times (effectively N^2)? That sounds inefficient.

EDIT: Updated with my intent

深巷少女 2024-11-08 08:42:11

好吧,如果使用非线程安全的 IQueryable(如实体框架查询),您可以做的一件事是枚举一个线程中的结果,然后将结果传递给新线程如有必要。

那么 IQueryable/IEnumerable 是否线程安全并不重要。

Well, one thing you could do, if working with an IQueryable that is not thread-safe (like an Entity Framework query) is to enumerate the results in one thread, but then pass the results to new threads as necessary.

Then it doesn't matter if the IQueryable/IEnumerable is thread-safe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文