好的,我需要一些帮助。当发送出需要可靠性的数据包时,它会被传递给ReliabilityLayer。从那里,ReliabilityLayer将该数据包添加到列表中,然后将其写入SocketLayer一次。然后,ReliabilityLayer生成一个具有2个定时器的线程。当数据包仍在列表中时,第一个定时器每250ms连续将数据包发送到SocketLayer。第二个计时器是超时时间。它会在2秒后引发异常。 ReliabilityLayer挂钩到数据包接收事件,当ACK数据包返回包含ReliabilityLayer数据包列表中数据包的校验和时,它应该删除它,允许线程退出。问题是多线程...跨线程访问列表给了我随机的空指针和其他问题。所以我必须以某种方式使其线程安全或重新思考这一切。我想知道是否有人可以帮助我?感谢
public void Write(NetworkPacket packet, ClientInfo client, Action<byte[], EndPoint> action)
{
if (CSL)
throw new Exception("ReliabilityLayer loaded for client use.");
if (!packet.Command.RequiresReliability())
throw new ArgumentException("Packet does not require reliability.");
//Add the packet to the reliability list
packetList.Add(packet);
//Send the packet to the socket layer.
action.Invoke(packet.RawData, client.EndPoint);
new Thread(() =>
{
Stopwatch timeout = new Stopwatch();
Stopwatch timer = new Stopwatch();
timer.Start();
timeout.Start();
while (packetList.Contains(packet))
{
//Still no response from the remote connection -> send another packet
if (timer.ElapsedMilliseconds > 256)
{
action.Invoke(packet.RawData, client.EndPoint);
timer.Restart();
}
//No response after 2 seconds -> throw exception
if (timeout.ElapsedMilliseconds > 2048)
{
throw new Exception("Client has not responded to the request.");
}
}
}).Start();
}
private void ssl_OnPacketReceived(object sender, ServerPacketEventArgs e)
{
if (e.Packet.Command != Command.Ack)
return;
//Find matching packet in the packetList
NetworkPacket packet = packetList.Find(pkt => pkt.Checksum == e.Packet.Data[0]); //e.Packet.Data[0] is the checksum of the packet that was send out.
if (packet != null)
{
//Remove it to allow thread to exit
packetList.Remove(packet);
}
}
答案 0 :(得分:3)
解决问题的最简单方法是使用lock()“保护”对List的任何调用。
您可以查看here如何操作。
简而言之,解释如下:
你应该按照方式“保护”不是线程安全的操作
private object private_obj_to_be_used = new object();
lock(private_obj_to_be_used)
{
/// not thread safe operation goes here<br/>
}
请注意,您不仅要“保护”插入或移除,还要读取。 或者您可以检查是否有适合您的“并发”课程。