C # сокеты и многопоточность

Я пытаюсь узнать больше о сокетах и потоках в C #. Я нашел много хороших ресурсов онлайн, чтобы помочь мне начать. Программа, которую я сделал до сих пор, является простой "человек посередине" приложение. Он разработан следующим образом: клиент & lt; - & gt; [приложение] & lt; - & gt; сервер

Учитывая следующий код, как я могу предотвратить запуск этого потока на 100% ЦП? Как я могу заставить поток ждать и блокировать данные и не выходить, когда клиент / сервер простаивает?

while (true)
       {
            lock (ClientState)
            {
                checkConnectionStatus(client, server);
            }

            if (clientStream.CanRead && clientStream.DataAvailable)
            {
                Byte[] bytes = new Byte[(client.ReceiveBufferSize)];

                IAsyncResult result = clientStream.BeginRead(bytes, 0, client.ReceiveBufferSize, null, null);
                int size = clientStream.EndRead(result);

                sendData(bytes, serverStream, size);
            }
            if (serverStream.CanRead && serverStream.DataAvailable)
            {
                Byte[] bytes = new byte[(server.ReceiveBufferSize)];

                IAsyncResult result = serverStream.BeginRead(bytes, 0, server.ReceiveBufferSize, null, null);
                int size = serverStream.EndRead(result);

                sendData(bytes, clientStream, size);
            }
        }

РЕДАКТИРОВАТЬ: решил опубликовать весь "Connection.cs" класс для всех, кто заинтересован. Я начинающий программист, так что я знаю, что здесь есть некоторые плохие практики кодирования. По сути, весь этот класс запускается в другом потоке и должен прекратиться, когда соединение (либо с сокетом клиента, либо с сокетом сервера) обрывается.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TCPRelay
{
public class Connection
{
    public delegate void delThreadSafeHandleException(System.Exception ex);
    public delegate void ConnectionDelegate(Connection conn);
    public int DataGridIndex;

    Main pMain;

    public TcpClient client { get; set; }
    public TcpClient server { get; set; }
    public String ClientState { get; set; }

    public string ListenPort { get; set; }
    public string remotePort { get; set; }

    public string listenAddress { get; set; }
    public string remoteAddress { get; set; }

    private TcpListener service { get; set; }

    private Main Form
    {
        get
        {
            return pMain;
        }
    }
    private NetworkStream clientStream { get; set; }
    private NetworkStream serverStream { get; set; }


    public Connection(TcpClient client, TcpClient server)
    {
        clientStream = client.GetStream();
        serverStream = server.GetStream();
    }

    public Connection(String srcAddress, int srcPort, String dstAddress, int dstPort, Main caller)
    {
        try
        {
            pMain = caller;
            TcpListener _service = new TcpListener((IPAddress.Parse(srcAddress)), srcPort);

            //Start the client service and add to connection property
            _service.Start();
            service = _service;


            //Set other useful parameters
            listenAddress = srcAddress;
            ListenPort = srcPort.ToString();

            remoteAddress = dstAddress;
            remotePort = dstPort.ToString();

            this.ClientState = "Listening";
        }
        catch (Exception ex)
        {
            pMain.HandleException(ex);
            Thread.CurrentThread.Abort();
        }

    }

    private TcpClient getServerConnection(String address, int port)
    {
        TcpClient client = new TcpClient(address, port);
        if (client.Connected)
        {
            return client;
        }
        else
        {
            throw new Exception(
                String.Format("Unable to connect to {0} on port {0}",
                address,
                port)
                );
        }
    }
    private void sendData(Byte[] databuf, NetworkStream stream, int size)
    {
        bool waiting = true;
        while (waiting)
        {
            if (stream.CanWrite)
            {
                waiting = false;
                stream.Write(databuf, 0, size);
            }
            else { throw new Exception("Unable to write to network stream"); }
        }
    }

    //Main Looping and data processing goes here
    public void ProcessClientRequest()
    {
        try
        {
            //Wait for a connection to the client
            TcpClient client = service.AcceptTcpClient();

            //Get the streams and set the peer endpoints
            this.clientStream = client.GetStream();
            this.client = client;

            //Now that we have a client, lets connect to our server endpoint
            TcpClient server = getServerConnection(remoteAddress, int.Parse(remotePort));

            //Set some useful parameters
            this.server = server;
            this.serverStream = server.GetStream();
        }
        catch (Exception ex)
        {
            lock (ClientState)
            {
                this.ClientState = ex.Message;    
            }

            CloseConnection();
            Thread.CurrentThread.Abort();
        }
        while (true)
       {
            lock (ClientState)
            {
                checkConnectionStatus(client, server);
            }

            if (clientStream.CanRead && clientStream.DataAvailable)
            {
                Byte[] bytes = new Byte[(client.ReceiveBufferSize)];

                IAsyncResult result = clientStream.BeginRead(bytes, 0, client.ReceiveBufferSize, null, null);
                int size = clientStream.EndRead(result);

                sendData(bytes, serverStream, size);
            }
            if (serverStream.CanRead && serverStream.DataAvailable)
            {
                Byte[] bytes = new byte[(server.ReceiveBufferSize)];

                IAsyncResult result = serverStream.BeginRead(bytes, 0, server.ReceiveBufferSize, null, null);
                int size = serverStream.EndRead(result);

                sendData(bytes, clientStream, size);
            }
        }
    }

    private void checkConnectionStatus(TcpClient _client, TcpClient _server)
    {
        try
        {
            if (_client.Client.Poll(0, SelectMode.SelectRead))
            {
                byte[] buff = new byte[1];
                if (_client.Client.Receive(buff, SocketFlags.Peek) == 0)
                {
                    this.ClientState = "Closed";
                    CloseConnection();
                    Thread.CurrentThread.Abort();
                }
            }
            else if (_server.Client.Poll(0, SelectMode.SelectRead))
            {
                byte[] buff = new byte[1];
                if (_server.Client.Receive(buff, SocketFlags.Peek) == 0)
                {
                    this.ClientState = "Closed";
                    CloseConnection();
                    Thread.CurrentThread.Abort();
                }
            }
            else { this.ClientState = "Connected"; }
        }
        catch (System.Net.Sockets.SocketException ex)
        {
            this.ClientState = ex.SocketErrorCode.ToString();
            CloseConnection();
            Thread.CurrentThread.Abort();
        }
    }

    public void CloseConnection()
    {
        if (clientStream != null)
        {
            clientStream.Close();
            clientStream.Dispose();
        }

        if (client != null)
        {
            client.Close();
        }

        if (serverStream != null)
        {
            serverStream.Close();
            serverStream.Dispose();
        }

        if (server != null)
        {
            server.Close();
        }

        if (service != null)
        {
            service.Stop();
        }
    }       
}

}

У меня также есть & quot; Main & quot; форма и «ConnectionManager» класс, с которым я играю.

Ответы на вопрос(2)

Ваш ответ на вопрос