2012-08-31 75 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