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

时间:2016-02-09 18:05:06

标签: c# asynchronous

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

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

我尝试的是设置一个bool,在循环访问集合并检查异步方法之前我将其关闭。如果它没有打开,我修改了一个不同的集合,并根据该程序的其余部分对原始集合进行更改。问题是异步方法在这个集合上也有一个循环,所以当它被连续快速调用时,它会干扰那个循环。

我认为更好的解决方案是设置代码,以便当bool表示集合不安全修改时,任何这些调用都会被延迟。但是,我不知道这是否是一个足够好的解决方案(因为我认为异步调用可能首先开始,然后程序可能会进入不安全的部分)。

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

 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:&#34; Collection已被修改;枚举操作可能无法执行。&#34;

如果在C#中有这种编程经验的人能给我一个指向如何解决这个问题的指示,我会很感激。

1 个答案:

答案 0 :(得分:1)

List<T>不是线程安全的,所以你不能让多个线程在同一时间读取和写入它。

您可以使用.NET框架提供的thread-safe collections之一来执行此操作。这种集合的一个例子是ConcurrentQueue<T>类。

引自上述参考文献:

  

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