2012-08-31 55 views
0

我确实遇到了多线程TCPClient应用程序的问题,每个客户端对象都有一个线程可以收集和发送消息,还有一个线程处理应该处理的任务(取决于消息)...(for示例创建并回答msg线程发送)。但是出了问题......应用程序几乎总是使用100%cpu(如果任何线程有任务,并且大多数情况下)。我也有一种感觉,一些线程的优先级小于其他线程(可以看到在一些操作系统中,线程1中的操作需要更长的时间,然后在线程2中检查...有没有什么好的方法来解决这个问题?多线程与TCPclient

我会喜欢一些帮助或一些提示! 任何不清楚的只是问:)

谢谢! /尼克

//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()块。这就是它应该如何工作!

如果你想写入东西的套接字,从另一个线程,(直接从父母thingy?),或更改您的设计使用异步读/写。循环使用,轮询事物,睡眠()等仅仅是浪费CPU和/或为您的应用程序添加可避免的延迟。

+0

好的,谢谢!你有任何例子如何做到这一点? – Nick3