C# - szalejący wątek obciąża w 100% procesor

0

Witam,
Mam problem z aplikacją wątkową (aplikacja klient-serwer). Program po uruchomieniu i wystartowaniu wątku pracuje normalnie, ale w pewnym momencie (najczęściej po odłączeniu klienta od serwera) zaczyna obciążać w 100% processor... W przypadku 2,3 klientów robi się masakra... kod wygląda tak:
Plik glowny.sc:

namespace Serwer
{
   
    class Program
    {
        static void Main(string[] args)
        {
            int sPort = 8081;          
            Hashtable klienci = new Hashtable();    
            try
            {
                IPAddress ip = IPAddress.Parse("192.168.0.1"); //169.254.27.49
                TcpListener serwer = new TcpListener(ip, sPort);
                serwer.Start();
                Console.WriteLine("Serwer is started");
                while (true)
                {
                    TcpClient client = serwer.AcceptTcpClient();
		            Console.WriteLine("polaczono");
                    new Thread(new ThreadStart( new ConnectionSession(client).run)).Start();
                }
            }
            catch (Exception see)
            {
                Console.WriteLine("Błąd : " + see.Message);
            }
        }
    }
}

Plik ConnectionSessioncode>Plik ConnectionSession.cs:
class ConnectionSession
{
protected int ClientID = 0;
private TcpClient Client;

public ConnectionSession(TcpClient client)
{
    Client = client;
}

public static int ByteIndexOf(byte[] searched, byte[] find, int start)
{
    bool matched = false;
    for (int index = start; index <= searched.Length - find.Length; ++index)
    {
        matched = true;
        for (int subIndex = 0; subIndex < find.Length; ++subIndex)
        {
            if (find[subIndex] != searched[index + subIndex])
            {
                matched = false;
                break;
            }
        }
        if (matched)
        {
            return index;
        }
    }
    return -1;
}
const int BUF_LEN = 256;
const int SYNC_FRAME_LEN = 8;

private bool ReadSynchroHeader()
{
    byte[] myReadBuffer = new byte[BUF_LEN];
    byte[] sync_frame = new byte[SYNC_FRAME_LEN];
    int i;
    for (i = 0; i < SYNC_FRAME_LEN; i++) {
        sync_frame[i] = (byte)(i+0x80);
    } 
    String s;
    uint read_ptr = 0, write_ptr = 0;
    if (Client.Connected)
    {
        StringBuilder dane = new StringBuilder();
        int numberOfBytesRead = 0, numberOfBytesToRead = 0;

        NetworkStream myNetworkStream = Client.GetStream();
        while (Client.Connected)
        {
            try
            {
                if (myNetworkStream.CanRead)
                {
                    numberOfBytesToRead = (int)(write_ptr >= read_ptr ? BUF_LEN - write_ptr : read_ptr - write_ptr);
                    myNetworkStream.ReadTimeout = 1000;
                    if (myNetworkStream.DataAvailable)
                    {
                        numberOfBytesRead = myNetworkStream.Read(myReadBuffer, (int)write_ptr, numberOfBytesToRead);
                        write_ptr = (uint)((write_ptr + numberOfBytesRead) % BUF_LEN);
                    }
                    while (read_ptr < write_ptr) { 
                        if (myReadBuffer[read_ptr] == 0xFA || myReadBuffer[read_ptr] == '$') {
                            break;
                        }
                        read_ptr = (read_ptr + 1) % BUF_LEN;
                    }
                    if (read_ptr == write_ptr) { 
                        read_ptr = write_ptr = 0;
                        continue;
                    }
                    try
                    {
                        if (myReadBuffer[read_ptr] == 0xFA)
                        {
                            if ((write_ptr - read_ptr + BUF_LEN) % BUF_LEN < SYNC_FRAME_LEN)
                            {
                                continue;
                            }
                            for (i = 0; i < SYNC_FRAME_LEN; i++)
                            {
                                sync_frame[i] = myReadBuffer[(read_ptr + i) % BUF_LEN];
                            }
                            if (sync_frame[1] != 0xF8)
                            {
                                s = "";
                                for (i = 0; i < SYNC_FRAME_LEN; i++) {
                                    s += String.Format("{0:X2} ", sync_frame[i]);
                                }
                                throw new FormatException("RE01 "+s);
                            }
                            int syncID = myReadBuffer[(read_ptr + 2) % BUF_LEN] | (myReadBuffer[(read_ptr + 3) % BUF_LEN] << 8);
                            uint unitID = (uint)myReadBuffer[(read_ptr + 4) % BUF_LEN] | (uint)(myReadBuffer[(read_ptr + 5) % BUF_LEN]) << 8 |
                                (uint)(myReadBuffer[(read_ptr + 6) % BUF_LEN]) << 16 | (uint)(myReadBuffer[(read_ptr + 7) % BUF_LEN]) << 24;
                            Console.WriteLine(String.Format("Odebrano sync: {0:X4}, UnitID {1:X8}\r\n", syncID, unitID));
                            SendMessage(sync_frame, SYNC_FRAME_LEN);
                            // przesuń wskaźnik odczytu (cała ramka odczytana)
                            read_ptr = (read_ptr + SYNC_FRAME_LEN) % BUF_LEN;
                        }
                        else if (myReadBuffer[read_ptr] == '$' || (myReadBuffer[read_ptr] >= '0' && myReadBuffer[read_ptr] <= '9'))
                        {
                            uint ptr = read_ptr+1;
                            while (ptr < write_ptr)
                            {
                                if (myReadBuffer[ptr] == '\n')
                                {
                                    break;
                                }
                                else if (myReadBuffer[ptr] == '$') {
                                    s = "";
                                    for (i = 0; i < ptr - read_ptr + 5; i++) {
                                        s += String.Format("{0:X2} ", myReadBuffer[(read_ptr + i)%BUF_LEN]);
                                    }
                                    throw new FormatException("RE04 " + s);
                                }
                                ptr = (ptr + 1) % BUF_LEN;
                            }
                            if (ptr == write_ptr)
                            {
                                continue;
                            }
                            byte[] buf = new byte[256];
                            byte[] b = Encoding.ASCII.GetBytes("Odebrano ramkę: ");
                            for (i = 0; i < b.Length; i++)
                            {
                                buf[i] = b[i];
                            }
                            for (i = 0; i < (write_ptr - read_ptr + BUF_LEN) % BUF_LEN; i++)
                            {
                                buf[16 + i] = myReadBuffer[(read_ptr + i) % BUF_LEN];
                            }
                            SendMessage(buf, i + 16);


                            read_ptr = (ptr + 1) % BUF_LEN;
                        }
                    }
                    catch (FormatException ex) { 
                        read_ptr = (read_ptr + 1) % BUF_LEN;
                    }
                }
            }
            catch (Exception se)
            {
                Console.WriteLine("Klient odłączony");
            }

        }

    }
    else
    {
        Console.WriteLine("Klient odłączony");
    }
    return true;
}

public static byte[] StrToByteArray(string str)
{
    System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    return encoding.GetBytes(str);
}
private void ReadInfo()
{
    if (Client.Connected)
    {
        StreamReader rclient = new StreamReader(Client.GetStream());
        
        while (true)
        {
            try
            {
                string dane = rclient.ReadLine();
                Console.WriteLine(dane);
                            
            }
            catch (Exception se)
            {
                Console.WriteLine("Błąd : " + se.Message);
            }
        }
    }
}
private void SendMessage(string message)
{
    if (String.IsNullOrEmpty(message))
        message = "\n";

    byte[] metaBuffer = Encoding.ASCII.GetBytes(message);
    Console.WriteLine("Sending:" + message);
}
private void SendMessage(byte[] message, int len)
{
    if (Client.Connected)
    {
        NetworkStream wclient = Client.GetStream();
        try
        {
            Console.WriteLine("Wysłalem:'" + Encoding.ASCII.GetString(message));
            wclient.Write(message, 0, len);
            wclient.Flush();
        }
        catch (Exception se)
        {
            Console.WriteLine("Błąd : " + se.Message);
        }

    }
}
public void run()
{
    ReadSynchroHeader();
}

}


Wiecie może jak to zoptymalizować?? :/


Z góry dzięki WIELKIE za pomoc:))

Pozdrawiam Northwest
0

Wywal to while(true) i użyj asynchronicznych metod do przyjmowania połączeń (BeginAcceptTcpClient itd).

0

Nie nie, to akurat jest dobrze, AcceptTcpClient jest blokujące i czeka na klienta. Błąd pewnie będzie w todzie obsługi ale kolega wkleił go tu tyle, że wątpie, żeby komuś się chciało go analizować :)

0
  1. Używaj znaczników <cpp> </cpp > i dodaj do tego jakieś komentarze, bo aktualnie pomimo wielu prób nie jestem w stanie tego zrozumieć(zwłaszcza funkcji ReadSynchroHeader - reszta jest dość oczywista) :/
  2. Unikaj czegoś takiego:
 while (true)
            {
                try
                {
                    string dane = rclient.ReadLine(); //to zatrzymuje prace programu?
                    Console.WriteLine(dane);
                                
                }
                catch (Exception se)
                {
                    Console.WriteLine("Błąd : " + se.Message);
                }

Jeżeli nie to sprawdź najpierw czy są juakieś nowe dane i ja nie ma to poczekaj np 0,5 sekundy zanim znowu sprawdzisz. Pętla while(true) często jest winowajcą spadku wydajności.

0

Sprawdz czy ta petla

while (Client.Connected)

sie konczy.

0

właśnie nie wiem co jest nie tak:/ testuje i niby powinno działać...:/ mógłbym się odezwać do Ciebie na maila, czy nie bardzo?? ;)

0

Nie powinno dzialac, bo w przypadku zerwania polaczenia wylapujesz latajace pewnie zewszad wyjatki W SRODKU petli. A status Connected moze nie byc zaktualizowany. Zrob wszystkie klauzule catch 'krzyczace' i zobacz czy gdzies cos dziwnego sie nie dzieje. Osobiscie dalbym swoja flage sygnalizujaca koniec petli komunikatow i modyfikowalbym ja mniej wiecej tam gdzie wypisujesz 'Klient odlaczony'.

PS. Tak, mozesz sie na maila odezwac, zreszta numer gadu tez masz ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1