Многопоточность с TCPclient

У меня есть проблема с многопоточным приложением TCPClient, каждый объект Client имеет поток, который получает и отправляет сообщения, и поток, который обрабатывает задачи, которые должны быть обработаны (в зависимости от сообщений)... (например, создает и отвечает, что MSG темы отправляет). Но что-то идет не так... приложение почти всегда использует 100% ЦП (если у какого-либо потока есть задача, и это в большинстве случаев). У меня также есть ощущение, что некоторые потоки имеют приоритеты меньше, чем другие (в некоторых журналах видно, что операция в потоке 1 занимает больше времени, чем в потоке 2 для проверки... Есть ли какой-нибудь хороший способ решить эту проблему?

Я хотел бы получить помощь или намеки! Что-нибудь непонятно, просто спросите:)

Спасибо! /Ник

//Waiting for TCP-connections and creating them as they arrive. Starts a Thread that handles the messages recieved and sent with this thread.
private void ListenForClients()
{
    try
    {

        this.tcpListener.Start();
        while (true)
        {
            TcpClient client = this.tcpListener.AcceptTcpClient();

            Connection c = new Connection(this.parent);
            connectionCollection.Add(c);
            Thread clientThread = new Thread(new ParameterizedThreadStart(c.HandleClientComm));

            threadCollection.Add(clientThread);
            clientThread.Start(client);
        }
    }
    catch (Exception e)
    {
    }
}
//Connection constructor, creates a ToDo-thread, this handles the messages (DB, Filewriting etc.) recieived and    creats new ones to be sent.
public Connection()
{
    this.todo = new ArrayList();
    todoT = new Thread(handleToDo);
    todoT.Start();
}
//Messagehandeling-thread
 public void HandleClientComm(object client)
{
    try
    {

        TcpClient server = (TcpClient)client;

        NetworkStream ns = server.GetStream();
        byte[] data = new byte[1024];
        string input, stringData;
        online = true;
        DateTime lastTime = DateTime.Now;

        while (true && this.online)
        {
            try
            {
                if (lastTime.AddMinutes(2) < DateTime.Now)
                    break;

                data = new byte[1024];
                if (ns.DataAvailable && ns.CanRead)
                {
                    int recv = ns.Read(data, 0, data.Length);
                    if (recv > 0)
                    {
                        lastTime = DateTime.Now;
                        if ((byte)data[recv - 1] == (byte)255)
                        {
                            int cnt = -1;
                            for (int i = 0; i < recv; i++)
                            {
                                if (data[i] == (byte)254)
                                {
                                    cnt = i;
                                    break;
                                }
                            }

                            int nr = recv - cnt - 2;
                            byte[] tmp = new byte[nr];

                            for (int i = 0; i < nr; i++)
                            {
                                tmp[i] = data[cnt + i + 1];
                            }
                            string crc = Encoding.UTF8.GetString(tmp);
                            stringData = Encoding.UTF8.GetString(data, 0, cnt);

                            MsgStruct msgs = new MsgStruct(stringData);
                            msgs.setCrc(crc);

                            addTodo(msgs);
                            if (msgs.getMsg()[0] == 'T' && this.type == 1)
                                this.parent.cStructHandler.sendAck(msgs, this.ID);
                            Console.WriteLine(todo.Count);

                        }
                    }
                }
                if (parent.cStructHandler.gotMsg(this.ID))
                {
                    MsgStruct tmpCs = parent.cStructHandler.getNextMsg(this.ID);

                    if (tmpCs.getMsg().Length != 0 && ns.CanWrite)
                    {
                        byte[] ba = Encoding.UTF8.GetBytes(tmpCs.getMsg());

                        if (tmpCs.getCrc() == "")
                        {
                            ulong tmp = CRC.calc_crc(ba, ba.Length);
                            tmpCs.setCrc(tmp.ToString("X"));
                        }

                        if (tmpCs.canSendByTimeout())
                        {
                            string crcStr = "?" + tmpCs.getCrc() + "?";
                            byte[] bb = Encoding.UTF8.GetBytes(crcStr);
                            crcStr = Encoding.UTF8.GetString(bb);
                            byte[] fullMsg = new byte[ba.Length + bb.Length];
                            bb[0] = 254;
                            bb[bb.Length - 1] = 255;

                            ba.CopyTo(fullMsg, 0);
                            bb.CopyTo(fullMsg, ba.Length);
                            string s = System.Text.UTF8Encoding.ASCII.GetString(fullMsg);

                            ns.Write(fullMsg, 0, fullMsg.Length);
                            if (!tmpCs.isAckNeeded())
                                parent.cStructHandler.removeNextMsg(this.ID);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                break;
            }

        }
        ns.Close();
        server.Close();
        dead = true;
    }
    catch (Exception e)
    {
        dead = true;
    }
}

//Todo-thread

public void handleToDo()
{
    try
    {
        int cnt = 0;
        while (true)
        {
            if (todo.Count > 0)
            {
                 //SWITCH CASE FOR DIFFERENT MESSAGE TYPES, DOING TASKS DEPENDING ON WHAT ONES...
            } 
            else
            {
                if (dead)
                {
                    todoT.Abort();
                    todoT = null;
                    break;
                }
            }
       }
  }
}

1 ответ

Решение

Прекратите проверять, доступны ли данные и т. Д., И просто разрешите блок read(). Вот как это должно работать!

Если вы хотите записать материал в сокет, сделайте это из другого потока (напрямую из родительской штуки?) Или измените свой дизайн на использование асинхронного чтения / записи.

Циклы, опросы, сон () и т. Д. - это просто трата процессора и / или добавление задержки в приложение.

Другие вопросы по тегам