100% CPU in multithreading applications

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Airslash
    New Member
    • Nov 2007
    • 221

    #1

    100% CPU in multithreading applications

    Still struggling with my client & server applications (see previous posts), but right now I've managed to gain a stead 10FPS when transfering images from the server to the client. So i'm making progress.

    The problem I'm currently experiencing, is that after a few seconds both my client and server application start claiming 100% of the CPU. I've placed Thread.Sleep() functions in the loops to make sure they're don't claim everything, but it's not helping. Below is the loop function for my 4 threads. Someone who can point out whats causing this?

    All Threads rely on the Thread class of .NET as a private member of my components. I've stripped all comments to ensure the code fits. I know some paths in the loops do not enter the sleep, but the logic here says that work needs to be performed. The idea is that the client sends a single request and the server pushes data back untill told to stop.

    Parser loop: parses the data received from the tcp socket.
    Code:
            void ProcessRoutine()
            {
                m_running = true;
    
                while(m_running)
                {
                    try
                    {
                        if (Buffer.Length > 0)
                        {
                            int start_position = 0;
    
                            while (start_position < Buffer.Length - 4)
                            {
                                string section = Encoding.ASCII.GetString(Buffer.Read(start_position, 4));
    
                                if (string.Equals(section, "@VT:"))
                                {
                                    int binary_size = BitConverter.ToInt32(Buffer.Read(start_position + 8, 4), 0);
         
                                    if ((start_position + 12 + binary_size) <= Buffer.Length)
                                    {
                                        byte[] symbol = Buffer.Read(start_position + 12 + binary_size, 1);
    
                                        if (Encoding.ASCII.GetString(symbol, 0, 1) == "#")
                                        {
                                            int end_position = start_position + 12 + binary_size + 1;
    
                                            IVTMessage message = IVTMessageBuilder.Construct(Buffer.Read(start_position, end_position));
    
                                            Buffer.Delete(start_position, end_position);
    
                                            RaiseOnMessageEvent(message);
    
                                            start_position = 0;
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        Buffer.Delete(start_position, start_position + 12 + binary_size + 1);
                                        start_position = 0;
                                        break;
                                    }
                                }
                                else
                                {
                                    start_position++;
                                }
                            }
                        }
                        else
                        {
                            Thread.Sleep(50);
                        }
                    }
                    catch (ThreadAbortException)
                    { 
                        m_running = false;
                        Debug.WriteLine("Background thread has been aborted.");
                    }
                    catch (Exception ex)
                    { 
                        Debug.WriteLine("   Exception message");
                        Debug.WriteLine("========================");                
                        Debug.WriteLine(ex.Message);
                        Debug.WriteLine(" InnerException message");
                        Debug.WriteLine("========================");
                        Debug.WriteLine(ex.InnerException.Message);
                        Debug.WriteLine("       StackTrace");
                        Debug.WriteLine("========================");
                        Debug.WriteLine(ex.StackTrace);
                    }
                }
            }
    TCP loop: polls the socket for data
    Code:
            void ListenRoutine()
            { 
                m_running = true;
    
                while (m_running)
                {
                    try
                    {
                        if (m_socket != null)
                        {
                            lock (m_lock)
                            {
                                if (Connected && (m_socket.Available > 0))
                                {
                                    int data_available = m_socket.Available;
                                    byte[] buffer = new byte[data_available];
                                    int bytes_read = m_socket.Receive(buffer, 0, data_available, SocketFlags.None);
    
                                    RaiseOnDataEvent(buffer, bytes_read, (m_socket.RemoteEndPoint as IPEndPoint).Address.ToString(), (m_socket.RemoteEndPoint as IPEndPoint).Port);
                                }
                            }
    
                            Thread.Sleep(50);
                        }
                        else
                        {
                            throw new Exception("The internal socket has been closed/disposed.");
                        }
                    }
                    catch (Exception ex)
                    {
                        RaiseOnErrorEvent("ListenRoutine", ex);
                        Disconnect();
                    }
                }
            }
    I know these are rather difficult things to ask, but I'm a bit clueless as where to look/proceed to find the issue.
    Also, code still belongs to me. You can use it if it's usefull, but please put in the source where you got it from.
  • TamusJRoyce
    New Member
    • Apr 2008
    • 108

    #2
    The first thing I see is that (start_position + 12 + binary_size) will always be constant. Because of this,

    Code:
    int binary_size = BitConverter.ToInt32(Buffer.Read(start_position + 8, 4), 0);
    
    if ((start_position + 12 + binary_size) <= Buffer.Length)
    {
      // Will always be true
    } else {
      // Will never be hit
      break; // break loop
    } // End if
    Maybe you want:

    Code:
    int binary_size = 0;
    
    while (m_running)
    {
      ...
      binary_size += BitConverter.ToInt32(Buffer.Read(start_position + 8, 4), 0);
    
      if ((start_position + 12 + binary_size) <= Buffer.Length)
      {
        // Will always be true
      } else {
        // Will never be hit
        break; // break loop
      } // End if
    I think this would cause your client to pull for data endlessly. I'm not sure why your server would spike at 100%, though. Since when it completes sending data, it should wait.

    I am guessing, however, that Buffer.Read() returns the number of bytes read, and not the location of the read.

    Comment

    • Airslash
      New Member
      • Nov 2007
      • 221

      #3
      I sorted it myself, one of the possible logic loops resulted in no Thread.Sleep beeing called, thus keeping the thread hogging all the CPU.

      The part with binary_size, is that I read out 4 bytes from the TCP message to determine how many data is still behind. But since I do not know if they're already received I had to do it this way.

      The new loop is 3 times shorter and has no CPU load anymore.

      Comment

      Working...