0

我确实有一个多线程 TCPClient 应用程序的问题,每个 Client 对象都有一个接收和发送消息的线程和一个处理应该处理的任务的线程(取决于消息)......(例如创建并回答味精线程发送)。但是出了点问题……应用程序几乎总是使用 100% 的 cpu(如果任何线程有任务,那是大部分时间)。我也有一种感觉,一些线程的优先级低于其他线程(可以在一些日志中看到,例如,线程 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;
                }
            }
       }
  }
}
4

1 回答 1

1

停止检查数据是否可用等,让 read() 阻塞。这就是它应该如何工作!

如果您想将内容写入套接字,请从另一个线程(直接从父对象?)执行此操作,或者更改您的设计以使用异步读/写。

循环、轮询、sleep() 等只是浪费 CPU 和/或为您的应用程序增加可避免的延迟。

于 2012-08-31T12:51:05.630 回答