Я получаю исключение InvalidOperationException, и я не знаю, почему

Это часть чата с несколькими пользователями, и я хочу десериализовать в цикле, чтобы каждое сообщение, которое я получаю, для каждого пользователя, которого я могу опубликовать (это на стороне сервера)

public class ServerDLL
{
    public TcpClient client { get; set; }
    public TcpListener listner { get; set; }

    public List<NetworkStream> clientStream = new List<NetworkStream>();

    public List<TcpClient> clientsList = new List<TcpClient>();

    string clientMsg;

    BinaryFormatter formatter = new BinaryFormatter();

    private object clientListLock = new object();

    public void startConnection()
    {
        Thread listnerThread = new Thread(ListnerFunc);
        listner.Start();
        listnerThread.Start();
        Thread waitForMeesage = new Thread(WaiterFunc);
        waitForMeesage.Start();
    }
    public void ListnerFunc()
    {
        while (true)
        {
            client = listner.AcceptTcpClient();
            clientStream.Add(client.GetStream());
            if (client.Connected)
            {
                lock (clientListLock)
                {
                    clientsList.Add(client);
                }
            }
        }
    }
    public void WaiterFunc()
    {
        while (true)
        {
            lock (clientListLock)
            {
                foreach (NetworkStream stream in clientStream)
                {
                    if (stream != null)
                    {
                        clientMsg = formatter.Deserialize(stream).ToString();
                    }
                }
            }
        }
    }

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

1 ответ

Во-первых, вам действительно нужно подождать в WaiterFunc(). Вращать процессор, как это, не очень хорошая идея.

При этом у вас есть общий ресурс с несколькими потоками в clientStream коллекция. Вы не можете изменить коллекцию во время перечисления (что делает ваш цикл while постоянно), вызывая исключение.

Вам нужно заблокировать доступ к этому списку:

private object clientListLock = new object();

public void ListnerFunc()
{
    while (true)
    {
        client = listner.AcceptTcpClient();

        lock(clientListLock)
        {
           clientStream.Add(client.GetStream());
           if (client.Connected)
           {
               clientsList.Add(client);
           }
        }
    }
}
public void WaiterFunc()
{
    while (true)
    {
        lock (clientListLock)
        {
           foreach (NetworkStream stream in clientStream)
           {
               clientMsg = formatter.Deserialize(stream).ToString();
           }
        }
    }
}
Другие вопросы по тегам