2016-02-09 3 views
0

Я работаю над программой, в 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); 
    } 
} 

В приведенном выше примере, когда NetworkDataReceived вызывается, когда SomeOtherMethod также работает, программа выходит из строя со следующим InvalidOperationException: " Коллекция была изменена, операция перечисления не может выполняться ».

Я был бы признателен, если бы кто-нибудь, у кого есть опыт программирования такого рода в C#, мог дать мне указатель на то, как решить эту проблему.

+2

Посмотрите на [потокобезопасные коллекции] (https://msdn.microsoft.com/en-us/library/dd997305 (v = vs.110) .aspx) –

+0

я изменил мой список в concurrentQueue и, похоже, решил проблему, большое спасибо! –

ответ

1

List<T> не является потокобезопасным, поэтому вы не можете иметь несколько потоков чтения и записи на него в одно и то же время.

Для этого вы можете использовать один из thread-safe collections, предоставляемый платформой .NET. Одним из примеров такой коллекции является класс ConcurrentQueue<T>.

Цитирование из приведенной выше ссылке:

Несколько потоков могут безопасно и эффективно добавлять или удалять элементы из этих коллекций, не требуя дополнительной синхронизации в пользовательском коде.

Смежные вопросы