使用TCPclient进行多线程处理

时间:2012-08-31 11:01:40

标签: c# multithreading tcpclient thread-synchronization

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

答案 0 :(得分:1)

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

如果你想把东西写进socket,可以从另一个线程(直接来自parent thingy?),或者改变你的设计以使用异步读/写。

循环,轮询,睡眠(等)只是浪费CPU和/或为应用添加可避免的延迟。

相关问题