0

マルチスレッドの TCPClient アプリケーションに問題があります。すべてのクライアント オブジェクトには、メッセージを送受信するスレッドと、(メッセージに応じて) 処理する必要があるタスクを処理するスレッドがあります... (たとえば、 msg スレッドが送信します)。しかし、何かがうまくいかない... アプリケーションはほとんど常に 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 に答える