0

我遇到一个问题,其中一个带有字节 [20] 的对象被传递到一个线程上的 BlockingCollection 中,而另一个线程使用 BlockingCollection.Take() 返回带有字节 [0] 的对象。我认为这是一个线程问题,但考虑到 BlockingCollection 是一个并发集合,我不知道发生在哪里或为什么会发生这种情况。

有时在 thread2 上,myclass2.mybytes 等于 byte[0]。非常感谢有关如何解决此问题的任何信息。

[编辑] 原始代码。我删除了上面似乎运行良好的代码,所以我花时间浏览了我的原始代码并发布了它。

消息缓冲区.cs

public class MessageBuffer : BlockingCollection<Message>
{
}

在具有 Listener() 和 ReceivedMessageHandler(object messageProcessor) 的类中

private MessageBuffer RecievedMessageBuffer;

在线程 1

    private void Listener()
    {
        while (this.IsListening)
        {
            try
            {
                Message message = Message.ReadMessage(this.Stream, this);
                if (message != null)
                {
                    this.RecievedMessageBuffer.Add(message);
                }
            }
            catch (IOException ex)
            {
                if (!this.Client.Connected)
                {
                    this.OnDisconnected();
                }
                else
                {
                    Logger.LogException(ex.ToString());
                    this.OnDisconnected();
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex.ToString());
                this.OnDisconnected();
            }
        }
    }

Message.ReadMessage(NetworkStream 流,iTcpConnectClient 客户端)

    public static Message ReadMessage(NetworkStream stream, iTcpConnectClient client)
    {
        int ClassType = -1;
        Message message = null;

        try
        {
            ClassType = stream.ReadByte();
            if (ClassType == -1)
            {
                return null;
            }

            if (!Message.IDTOCLASS.ContainsKey((byte)ClassType))
            {
                throw new IOException("Class type not found");
            }

            message = Message.GetNewMessage((byte)ClassType);
            message.Client = client;
            message.ReadData(stream);

            if (message.Buffer.Length < message.MessageSize + Message.HeaderSize)
            {
                return null;
            }

        }
        catch (IOException ex)
        {
            Logger.LogException(ex.ToString());
            throw ex;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex.ToString());
            //throw ex;
        }

        return message;
    }

在线程 2

    private void ReceivedMessageHandler(object messageProcessor)
    {
        if (messageProcessor != null)
        {
            while (this.IsListening)
            {
                Message message = this.RecievedMessageBuffer.Take();
                message.Reconstruct();
                message.HandleMessage(messageProcessor);
            }
        }
        else
        {
            while (this.IsListening)
            {
                Message message = this.RecievedMessageBuffer.Take();
                message.Reconstruct();
                message.HandleMessage();
            }
        }
    }

PlayerStateMessage.cs

public class PlayerStateMessage : Message
{
    public GameObject PlayerState;

    public override int MessageSize
    {
        get { return 12; }
    }

    public PlayerStateMessage()
        : base()
    {
        this.PlayerState = new GameObject();
    }

    public PlayerStateMessage(GameObject playerState)
    {
        this.PlayerState = playerState;
    }

    public override void Reconstruct()
    {
        this.PlayerState.Poisiton = this.GetVector2FromBuffer(0);
        this.PlayerState.Rotation = this.GetFloatFromBuffer(8);
        base.Reconstruct();
    }

    public override void Deconstruct()
    {
        this.CreateBuffer();
        this.AddToBuffer(this.PlayerState.Poisiton, 0);
        this.AddToBuffer(this.PlayerState.Rotation, 8);
        base.Deconstruct();
    }

    public override void HandleMessage(object messageProcessor)
    {
        ((MessageProcessor)messageProcessor).ProcessPlayerStateMessage(this);
    }
}

Message.GetVector2FromBuffer(int bufferlocation) 这是抛出异常的地方,因为 this.Buffer 应该是 byte[0] 而应该是 byte[20]。

    public Vector2 GetVector2FromBuffer(int bufferlocation)
    {
        return new Vector2(
            BitConverter.ToSingle(this.Buffer, Message.HeaderSize + bufferlocation),
            BitConverter.ToSingle(this.Buffer, Message.HeaderSize + bufferlocation + 4));
    }
4

1 回答 1

0

所以这是一个很难解决的问题。据我所知,我只是收到随机字节,所以我改变了我的“消息”相当多。现在有一个头缓冲区和一个数据缓冲区。整个消息由一个开始标记和一个结束标记封装,而标题和数据缓冲区分别由不同的标记封装。这使我能够判断何时收到错误数据并可以丢弃该消息。如果消息确实被丢弃,在下一条消息读取时,它不会只检查接收到的前 4 个字节是否是开始标记,而是会逐字节读取,直到读取的最后 4 个字节等于标记。

于 2012-07-17T23:17:06.587 回答