connection.Thread.Start(connection)
начинает новый поток с вызова ProcessConnection
, передавая connection
в качестве аргумента state
.Выполнение в текущем потоке немедленно продолжается со следующей строки, пока ProcessConnection
выполняется в новом потоке.
ProcessConnection
получает объект Socket
из объекта ConnectionInfo
, переданного ему AcceptConnections
, и ожидает получения данных из сокета.Когда он получает данные, он проходит по всем другим ConnectionInfo
объектам в коллекции connections
и отправляет эти данные каждому из них по порядку.
Так что же здесь происходит одновременно?Ну, у нас есть начальный поток (назовите его Thread 0), выполняющий AcceptConnections
в бесконечном цикле.И затем для каждого соединения с сокетом, которое мы приняли, у нас есть поток, выполняющий ProcessConnection
.
Блокировки необходимы, потому что ProcessConnection
использует foreach
для циклического прохождения по известным соединениям для отправки им данных.Если поток 0 добавит новое соединение в коллекцию во время перечисления коллекции в foreach
, InvalidOperationException
будет добавлено в ProcessConnection
.
lock
предотвращает параллелизмпроблема в этом случае, но это также вызывает потенциальную проблему производительности.Он не только запрещает AcceptConnections
изменять коллекцию, пока ProcessConnection
ее перечисляет.Это также предотвращает одновременное перечисление коллекции любыми двумя потоками, выполняющими ProcessConnection
.В этом случае лучшим выбором будет ReaderWriterLockSlim
, который позволит нескольким потокам одновременно читать коллекцию.