用于在循环期间干扰收集的异步调用的标准解决方案

本文关键字:异步 调用 标准 解决方案 循环 干扰 用于 | 更新日期: 2023-09-27 18:33:58

我正在开发一个使用异步网络调用的 c# 程序。其中一些修改了程序的其余部分不时循环访问的集合。问题是,当异步调用在循环期间尝试修改为集合时,会引发异常并且程序崩溃。

我对这种类型的编程相当陌生,这似乎是一个应该有一个标准解决方案的常见问题。

我尝试的是设置一个布尔值,在循环访问集合并签入异步方法之前关闭该布尔值。如果它不在 我修改了不同的集合,并基于该集合对程序其余部分中的原始集合进行更改。问题是异步方法在此集合上也有一个循环,因此当它被快速连续调用时,它可能会干扰该循环。

我认为更好的解决方案是设置代码,这样虽然表示集合不安全修改的布尔值为真,但这些调用中的任何一个都会延迟。但是我不知道这是否是一个足够好的解决方案(因为我认为异步调用可以首先开始,然后程序可能会到达不安全的部分(。

这不是实际的程序,但为了清楚起见,这是一个问题示例:

 private List<Stuff> myList = new List();
 private void NetworkDataReceived(Stuff s)
 {
   myList.Add(s);
 }
 private void SomeOtherMethod()
 {
   foreach(Stuff s in myList)
   {
     DoSomethingWithStuff(s);
   }
 }

在上面的示例中,当在 SomeOtherMethod 也运行时调用 NetworkDataReceived 时,程序崩溃并显示以下 InvalidOperationException:"集合已修改;枚举操作可能无法执行。

如果有人有这种 C# 编程经验的人可以给我一个如何解决这个问题的指针,我将不胜感激。

用于在循环期间干扰收集的异步调用的标准解决方案

List<T>不是线程安全的,因此您不能同时有多个线程读取和写入它。

可以使用 .NET 框架提供的线程安全集合之一来执行此操作。此类集合的一个示例是 ConcurrentQueue<T> 类。

引用上面的参考资料:

多个线程可以安全高效地在这些集合中添加或删除项,而无需在用户代码中进行额外的同步。