C# 我得到一个异常InvalidOperationException,我没有';我不知道为什么

C# 我得到一个异常InvalidOperationException,我没有';我不知道为什么,c#,exception,foreach,chat,invalidoperationexception,C#,Exception,Foreach,Chat,Invalidoperationexception,这是多用户聊天的一部分,我想在循环中反序列化,以便我收到的每个用户的消息都可以发布(这是服务器端) 公共类ServerDLL { 公共TcpClient客户端{get;set;} 公共TcpListener列表器{get;set;} public List clientStream=新列表(); public List clientsList=新列表(); 字符串clientMsg; BinaryFormatter formatter=新的BinaryFormatter(); 私有对象clien

这是多用户聊天的一部分,我想在循环中反序列化,以便我收到的每个用户的消息都可以发布(这是服务器端)

公共类ServerDLL
{
公共TcpClient客户端{get;set;}
公共TcpListener列表器{get;set;}
public List clientStream=新列表();
public List clientsList=新列表();
字符串clientMsg;
BinaryFormatter formatter=新的BinaryFormatter();
私有对象clientListLock=新对象();
公共无效startConnection()
{
线程listnerThread=新线程(ListnerFunc);
Start();
listnerThread.Start();
线程waitForMeesage=新线程(WaiterFunc);
waitForMeesage.Start();
}
public void ListnerFunc()
{
while(true)
{
client=listner.AcceptTcpClient();
clientStream.Add(client.GetStream());
如果(客户端已连接)
{
锁(clientListLock)
{
clientsList.Add(客户端);
}
}
}
}
公共无效WaiterFunc()
{
while(true)
{
锁(clientListLock)
{
foreach(客户端流中的网络流)
{
if(流!=null)
{
clientMsg=formatter.Deserialize(stream.ToString();
}
}
}
}
}

现在,当我从客户端发送消息时,异常会弹出。

首先,您确实应该在WaiterFunc()中进行某种等待。这样旋转CPU不是一个好主意

也就是说,您在
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();
           }
        }
    }
}

首先,您真的应该在WaiterFunc()中放入某种等待。这样旋转CPU不是一个好主意

也就是说,您在
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();
           }
        }
    }
}

您必须实现生产者-消费者模式。您必须实现生产者-消费者模式。您的建议正在解决问题,但它缺少线程的使用。@HamletHakobyan,它的线程数与操作代码的线程数一样多,我试图解释交叉线程访问是问题所在。您建议我更改什么?我认为它必须更改当我知道while循环没有真正工作时,它在反序列化行中等待,直到它得到要反序列化的内容为止,它不是一次又一次地反序列化null…并且感谢您在解释我理解我的错误时给出的快速回答problem@Theiceman如果“反序列化”正在等待,直到它得到一些东西,然后您会遇到不同的问题。您可能应该为每个客户端使用不同的侦听线程(而不是在同一个线程中执行)这样,每个客户端都可以随时发送。您的客户端将一直阻止,直到它所在的客户端发送,然后再处理其他客户端。您的建议是解决问题,但它缺少线程的使用。@HamletHakobyan,它的线程数与操作代码的线程数一样多,我试图解释跨线程访问是问题所在。您的建议是什么暗示我改变?我认为它必须改变OP,我已经评论了OP。你在我的WaiterFunc()中加入等待是什么意思正如我所知,while循环并没有真正起作用,它在反序列化行中等待,直到它得到一些要反序列化的内容为止,它并不是一次又一次地反序列化null…感谢您在解释我理解我的想法时给出的快速回答problem@Theiceman如果“反序列化”“正在等待,直到它得到一些东西,那么你有一个不同的问题。你可能应该为每个客户端有一个不同的侦听线程(而不是在同一个线程中执行),这样每个客户端都可以随时发送。你的将阻塞,直到它所在的客户端发送,然后才处理其他客户端。