0

byte[20] を持つオブジェクトが 1 つのスレッドで BlockingCollection に渡され、別のスレッドが BlockingCollection.Take() を使用して byte[0] を持つオブジェクトを返すという問題があります。これはスレッドの問題だと思いますが、BlockingCollection が並行コレクションであることを考えると、どこで、またはなぜこれが起こっているのかわかりません。

スレッド 2 では、myclass2.mybytes が byte[0] と等しい場合があります。これを修正する方法に関する情報は大歓迎です。

[編集] 元のコード。問題なく動作するように見えた上記のコードを削除したので、時間をかけて元のコードを調べて投稿しました。

MessageBuffer.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[20] である必要があるのに 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));
    }
4

1 に答える 1

0

そのため、これは解決するのが難しい問題でした。私の知る限り、ランダムなバイトを受信して​​いたので、「メッセージ」をかなり変更しました。現在、ヘッダー バッファーとデータ バッファーがあります。メッセージ全体は開始マーカーと終了マーカーでカプセル化され、ヘッダーとデータ バッファーはそれぞれ異なるマーカーでカプセル化されます。これにより、不正なデータを受信したときにメッセージを破棄できるようになりました。メッセージが破棄された場合、次のメッセージの読み取り時に、受信した最初の 4 バイトが開始マーカーであるかどうかを確認するだけでなく、最後に読み取った 4 バイトがマーカーと等しくなるまでバイトごとに読み取ります。

于 2012-07-17T23:17:06.587 に答える