Не блокируется поток в клиент-серверном приложении (чат) - C#

Узнай цену своей работы

Формулировка задачи:

Всем доброго дня! На лабораторной (да я студент) задали реализовать чат. В ходе реализации решил использовать асинхроный метод приема данных от клиента, и путём вызова событий обрабатыват их (например при приходе текстового сообщения от клиента вызывается событие getTextMs). Также на серверной части хранится список всех подключёных пользователей (для рассылки полученых сообщений). При любом обращении к списку пользователей я использую lock чтобы не вылететь из перечисления. Например когда пользователь выходит из сети, то вызывается функция которая удаляет его из списка, и если другой поток в это время рассылал данный - выходит не очень красиво. Собственно проблема -

указаный элемент в lock не блокируется.

И когда я запускаю к примеру сразу десять окон и одновременно их отключаю - сервер вылетает с

InvalidOperationException Collection was modified; enumeration operation may not execute.

(то есть у меня во время перечисления this.clientList изменился).
        private readonly Object locker = new Object();
...
        private void client_getExit(object sender, ExitEventArgs e)
        {
            ServerClient client = sender as ServerClient;
            lock (this.locker)
            {
                this.clientList.Remove(client);
                if (client.IsAuthorization) 
                {
                    //рассылка всем пользователям, что клиент вышел из сети.
                    OutServerMessage serverMessage = new OutServerMessage(client.Id);
                    foreach (ServerClient serverClient in this.clientList)
                    {
                        serverClient.SendMessage(serverMessage);
                    } 
                }
            }
        }
this.clientList - список всех подключенных пользователей. serverMessage - сообщение, которое отправляется на клиент. serverClient.SendMessage - отправление текущего сообщения пользователю. Я сначала думал, что всё это каким-то чудом висит в одном потоке, но проверка по System.Threading.Thread.CurrentThread.ManagedThreadId показала разные числа (надеюсь то смотрел). также решил ради "шутки" добавить ещё одну переменную и посмотреть в дэбаге, при ошибке
        private readonly Object locker = new Object();
        int kso = 0;
...
        private void client_getExit(object sender, ExitEventArgs e)
        {
            ServerClient client = sender as ServerClient;
            lock (this.locker)
            {
                this.kso++;
 
                this.clientList.Remove(client);
                if (client.IsAuthorization) 
                {
                    //рассылка всем пользователям, что клиент вышел из сети.
                    OutServerMessage serverMessage = new OutServerMessage(client.Id);
                    foreach (ServerClient serverClient in this.clientList)
                    {
                        serverClient.SendMessage(serverMessage);
                    } 
                }
 
                this.kso--;
            }
        }
так вот... переменная this.kso при вылавливании ошибки показывала от 2 до 5. P.S. Пожалуйста, отзовитесь люди! Я уже второй день с этой ошибкой воюю... ='(

Решение задачи: «Не блокируется поток в клиент-серверном приложении (чат)»

textual
Листинг программы
public class DataСhannel
{
  public void Send(Message message)
  {
                . . . 
                try
                {
                    this.socket.Send(sendHead);
                    this.socket.Send(array);
                }
                catch (SocketException)
                {
                    if (this.onClose != null)
                        this.onClose(this, new OnCloseEventArgs());
                }
  }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 3.833 из 5
Похожие ответы