BlockingCollection存在字节数组问题

时间:2012-07-10 09:53:18

标签: c# multithreading blockingcollection

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

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

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

MessageBuffer.cs

public class MessageBuffer : BlockingCollection<Message>
{
}

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

private MessageBuffer RecievedMessageBuffer;

在Thread1上

    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;
    }

在Thread2上

    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) 这是抛出异常的地方,因为当它应该是byte [20]时,this.Buffer是byte [0]。

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

1 个答案:

答案 0 :(得分:0)

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