TcpClient снова не принимает данные

Есть класс, принимающий данные через TcpClient (TcpConnection). Полностью работает. Есть его наследник - RsaDecorator. Его метод Connect() (строка 240) должен передавать свой публичный ключ и получать чужой в ответ. Для этого есть методы SendKey() и ReceiveKey(). Они почему-то не работают (блок "Не работает") :). Точнее, происходит вход в бесконечный цикл ожидания ответа. Таска с получением ответа запущена с обоих сторон, проверял :). Для проверки в метод добавил обмен сообщениями - всё работает (блок "Работает"). Не ясно, в чём проблема.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestProject
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Run(() =>
            {
                Thread.CurrentThread.Name = "Server thread";
                TcpListener listener = new TcpListener(IPAddress.Any, 13888);
                listener.Start();
                TcpConnection client = new RsaDecorator(new TcpConnection(listener.AcceptTcpClient()));
                Console.WriteLine("Server: new connection!");
                client.ReceivingState = ReceivingState.Method;
                client.Connect();
                while (client.GetReceivedCount() == 0) Thread.Sleep(100);
                Console.WriteLine($"Server (available: {client.GetReceivedCount()}): " +
                    $"has been received message: {Encoding.UTF8.GetString(client.GetReceived().ToArray())}");
            });
            Task.Run(() =>
            {
                Thread.CurrentThread.Name = "Client thread";
                TcpConnection connection = new RsaDecorator(new TcpConnection());
                connection.SetEndPoint("127.0.0.1", 13888);
                connection.ReceivingState = ReceivingState.Method;
                connection.Connect();
                if (connection.IsActive())
                {
                    connection.Send(Encoding.UTF8.GetBytes("Text"));
                }
            });
            Console.ReadLine();
        }
    }
    public class TcpConnection
    {
        private readonly TcpClient client;
        private BinaryReader reader;
        private BinaryWriter writer;
        private NetworkStream stream;

        private string ip;
        private int port;

        private Task receiveTask;

        private readonly List<byte> receivedBytes = new List<byte>();

        public virtual ReceivingState ReceivingState
        {
            get
            {
                lock (receiveStateObject)
                {
                    return receivingState;
                }
            }
            set
            {
                lock (receiveStateObject)
                {
                    receivingState = value;
                }
            }
        }
        private ReceivingState receivingState = ReceivingState.Both;
        private object receiveStateObject = new object();

        public virtual event ReceiveData OnReceiveData;

        public TcpConnection(TcpClient client)
        {
            this.client = client;
            if (IsActive())
            {
                reader = new BinaryReader(client.GetStream());
                writer = new BinaryWriter(client.GetStream());
                receiveTask = Task.Run(() => BeginReceive());
            }
        }
        public TcpConnection()
            : this(new TcpClient())
        { }

        public virtual bool IsActive()
        {
            try
            {
                client.GetStream().Write(new byte[0]);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public virtual void SetEndPoint(string ip, int port)
        {
            this.ip = ip;
            this.port = port;
        }

        public virtual void Connect()
        {
            if (ip != null && port != 0)
            {
                client.Connect(ip, port);
                reader = new BinaryReader(client.GetStream());
                writer = new BinaryWriter(client.GetStream());
                stream = client.GetStream();
                receiveTask = Task.Run(() => BeginReceive());
            }
        }

        public virtual void Disconnect()
        {
            client.Close();
            reader.Close();
            writer.Close();
            stream.Close();
        }

        public virtual void Send(byte[] message)
        {
            if (IsActive())
            {
                writer.Write(message);
                writer.Flush();
            }
        }

        private void BeginReceive()
        {
            Thread.CurrentThread.Name = "Receive thread";
            while (true)
            {
                if (IsActive() && client.Available != 0)
                {
                    byte[] temp = reader.ReadBytes(client.Available);

                    lock (receiveStateObject)
                    {
                        if (ReceivingState == ReceivingState.Method || ReceivingState == ReceivingState.Both)
                            lock (receivedBytes)
                            {
                                receivedBytes.AddRange(temp);
                            }
                        if (ReceivingState == ReceivingState.Event || ReceivingState == ReceivingState.Both)
                            lock (receivedBytes)
                            {
                                OnReceiveData?.Invoke(temp.ToArray());
                            }
                    }
                }
                else
                {
                    Thread.Sleep(100);
                }
            }
        }

        public virtual IEnumerable<byte> GetReceived()
        {
            lock (receivedBytes)
            {
                foreach (var item in receivedBytes)
                    yield return item;
                receivedBytes.Clear();
            }
        }

        public virtual int GetReceivedCount()
        {
            lock (receivedBytes)
            {
                return receivedBytes.Count;
            }
        }
    }

    public class RsaDecorator:TcpConnection
    {
        private TcpConnection innerConnection;

        private RSAParameters publicKey;
        private RSAParameters privateKey;

        private readonly KeyGen keyGen = new KeyGen();

        public override ReceivingState ReceivingState
        {
            get => innerConnection.ReceivingState;
            set => innerConnection.ReceivingState = value;
        }
        public override event ReceiveData OnReceiveData;

        private bool connectionCompleted = false;

        public RsaDecorator(TcpConnection connection)
        {
            innerConnection = connection;
            innerConnection.OnReceiveData += (byte[] message) =>
            {
                OnReceiveData?.Invoke(Decrypt(message));
            };
        }

        private void SendKey(RSAParameters key)
        {
            RsaSerializable serializableKey = new RsaSerializable(key);
            BinaryFormatter formatter = new BinaryFormatter();
            using Stream stream = new MemoryStream();
            formatter.Serialize(stream, serializableKey);
            Console.WriteLine($"Length of stream: {stream.Length}");
            innerConnection.Send(stream.ToArray());
        }
        private RSAParameters ReceiveKey()
        {
            BinaryFormatter formatter = new BinaryFormatter();
            using Stream stream = new MemoryStream();
            while (innerConnection.GetReceivedCount() == 0) Thread.Sleep(100);
            stream.Write(innerConnection.GetReceived().ToArray());
            return ((RsaSerializable)formatter.Deserialize(stream)).GetAsRsaParameters();
        }

        public override void Connect()
        {
            if (!innerConnection.IsActive())
                innerConnection.Connect();
            privateKey = keyGen.GetRSAParameters();

            // Не работает
            SendKey(privateKey);
            publicKey = ReceiveKey();

            // Работает
            //innerConnection.Send(Encoding.UTF8.GetBytes("Some text"));
            //while (innerConnection.GetReceivedCount() == 0) Thread.Sleep(100);
            //Console.WriteLine(Encoding.UTF8.GetString(innerConnection.GetReceived().ToArray()));

            connectionCompleted = true;
        }

        public override void Disconnect()
        {
            connectionCompleted = false;
            innerConnection.Disconnect();
        }

        public override bool IsActive()
        {
            return connectionCompleted && innerConnection.IsActive();
        }

        public override IEnumerable<byte> GetReceived()
        {
            return Decrypt(innerConnection.GetReceived().ToArray());
        }

        public override void Send(byte[] message)
        {
            innerConnection.Send(Encrypt(message));
        }

        public override void SetEndPoint(string ip, int port)
        {
            innerConnection.SetEndPoint(ip, port);
        }

        private byte[] Encrypt(byte[] message)
        {
            using var rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(publicKey);
            return rsa.Encrypt(message, false);
        }

        private byte[] Decrypt(byte[] message)
        {
            using var rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(privateKey);
            return rsa.Decrypt(message, false);
        }

        public override int GetReceivedCount()
        {
            return innerConnection.GetReceivedCount();
        }

        [Serializable]
        public class RsaSerializable
        {
            public byte[] Exponent;
            public byte[] Modulus;

            public RsaSerializable(RSAParameters parameters)
            {
                Exponent = parameters.Exponent;
                Modulus = parameters.Modulus;
            }
            public RSAParameters GetAsRsaParameters()
            {
                return new RSAParameters() { Exponent = Exponent, Modulus = Modulus };
            }
        }

        private class KeyGen
        {

            internal int KeysCount { get; set; } = 2;

            private Queue<RSAParameters> Keys;

            /// <summary>
            ///  Метод, возвращающий ключ
            /// </summary>
            internal RSAParameters GetRSAParameters()
            {
                // Заполнение очереди с ключами до указанного количества +1
                for (int i = 0; i <= KeysCount - Keys.Count; i++)
                    GenerateKeyToQueue();

                // Ожидание появления ключей в очереди
                while (Keys.Count == 0) Thread.Sleep(100);

                // Извлечение результата
                lock (Keys)
                {
                    return Keys.Dequeue();
                }
            }

            internal KeyGen()
            {

                Keys = new Queue<RSAParameters>();
                GenerateKeyToQueue();

            }

            /// <summary>
            ///  Метод, генерирующий ключ и добавляющий его в очередь
            /// </summary>
            private void GenerateKeyToQueue()
            {
                // Запуск асинхронной генерации
                Task.Run(() =>
                {
                    // Генерация
                    using var rsa = new RSACryptoServiceProvider();
                    RSAParameters result = rsa.ExportParameters(true);

                    // Добавление в очередь
                    lock (Keys)
                    {
                        Keys.Enqueue(result);
                    }
                });
            }
        }
    }
    public enum ReceivingState : byte
    {
        Method,
        Event,
        Both
    }
    public delegate void ReceiveData(byte[] message);
}

Ответы (0 шт):