Как использовать многопоточность, блокировки, сокет-программирование - PullRequest
1 голос
/ 29 июня 2010

В течение последних 48 часов я пытался понять Multithreading и Socket Programming.Я попытался реализовать программирование сокетов и имел успех, когда не использовал многопоточность.Я новичок в обеих темах и поднял 2-3 вопроса о стеке, нуждающихся в помощи.

После долгих поисков я нашел статью , которая объясняет Socket Programming и Multithreading, но у меня все еще есть много сомнений в этой статье, и я застрялна Figure 5 в статье.

private void AcceptConnections()
    {
        while (true)
        {
            // Accept a connection
            Socket socket = _serverSocket.Accept();
            ConnectionInfo connection = new ConnectionInfo();
            connection.Socket = socket;

            // Create the thread for the receives.
            connection.Thread = new Thread(ProcessConnection);
            connection.Thread.IsBackground = true;
            connection.Thread.Start(connection);

            // Store the socket
            lock (_connections) _connections.Add(connection);
        }
    }

В самой последней строке вы видите, что lock был взят и 3-4 строки выше delegate ProcessConnection ограничены.

На данный момент я неПонятно, как работает этот замок.Что происходит за кулисами, когда взяли замок?Почему автор использовал здесь блокировку?Что бы произошло, если бы не было взято замка?Как работает поток ProcessConnection?Какие вещи происходят одновременно?

Я запутался со всеми этими вопросами

Я знаю, что здесь есть список вопросов, но было бы очень полезно, если бы вы помогли мне понятьМетодология работы с многопоточностью.

Ответы [ 3 ]

2 голосов
/ 29 июня 2010

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, который позволит нескольким потокам одновременно читать коллекцию.

1 голос
/ 29 июня 2010

В C #, и я думаю, что в CLR в целом каждый объект может иметь монитор , связанный с ним.Здесь _connections - это коллекция, которая, возможно, используется совместно с потоками, запущенными из этой самой функции (они, вероятно, удаляют соединения из коллекции, когда они сделаны).Коллекции в C # не синхронизируются по умолчанию, вы должны делать это явно, поэтому оператор lock(_connections) предотвращает гонок в коллекции.

1 голос
/ 29 июня 2010

Я предполагаю, что _connections - это List<ConnectionInfo>: списки не являются потокобезопасными, и этот поток добавляет элементы в этот список.Если другой поток будет одновременно удалять элемент, результаты будут непредсказуемыми.Поэтому вы должны убедиться, что никакой другой процесс не может получить к нему доступ, используя блокировку.

connection.Thread.Start(connection); запускает новый поток, который начнется немедленно или через некоторое время.Текущий поток (код, который вы видите здесь) не будет иметь никакого контроля над ним.Этот новый поток снабжен объектом ConnectionInfo, поэтому он будет знать, на каком сокете выполнять задачи.Пока текущий поток продолжает прослушивать новых клиентов, функция ProcessConnection будет обрабатывать недавно принятого клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...