ChanChan
ChanChan

Reputation: 19

Reduce C# Application CPU Usage

I am creating a program that will TCP Event Receiver. Every time I start the program having is CPU consumption 30% and try to publish it and try to run multiple application it gradually consume 100% of my CPU Usage

namespace TCPIPReceiver

{ public partial class Form1 : Form { SimpleTcpServer server; SqlConnection con; BackgroundWorker backgroundworker1; Thread INCOMING;

    bool rxv = false;
    string rxvmsg;
    public Form1()
    {
        InitializeComponent();
        loadit();
    }
    private void loadit()
    {
        server = new SimpleTcpServer();
        server.Delimiter = 0x13;
        server.StringEncoder = Encoding.UTF8;
        server.DataReceived += server_datarx;
        backgroundworker1 = new BackgroundWorker();
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        INCOMING = new Thread(INCOMINGTHREAD);

    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            if(rxv)
            {
                rxv = false;
                INCOMING = new Thread(INCOMINGTHREAD);
                INCOMING.Start();
            }
            if (backgroundWorker1.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }
    }

    private void server_datarx(object sender, SimpleTCP.Message e)
    {
        rxvmsg = e.MessageString;
        rxv = true;
        SetText(rxvmsg);
        e.ReplyLine("\u0006");
    }

    delegate void SetTextCallback(string text);
    private void SetText(string text)
    {
        if (this.textBox2.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            if (text != null)
            {
                this.textBox2.AppendText(Environment.NewLine);
                this.textBox2.AppendText(text);
            }
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        if((textBox1.Text == "") || (textBox3.Text == ""))
        {
            MessageBox.Show("All fields are required","System Notification",MessageBoxButtons.OK,MessageBoxIcon.Information);
        }
        else
        {
            Cursor.Current = Cursors.WaitCursor;
            startit();
            Cursor.Current = Cursors.Default;

        }
    }

    private void startit()
    {
        if (button1.Text == "Start")
        {
            con = new SqlConnection(textBox3.Text);
            if(connectionchecker())
            {
                backgroundWorker1.RunWorkerAsync();
                server.Start(Convert.ToInt32(textBox1.Text));
                button1.Text = "Stop";
                SetText("Established Database Connection");
                settingslocker(true);
                

            }
            else
            {
                MessageBox.Show("Please check database connection", "Database connection error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        else if (button1.Text == "Stop")
        {
            server.Stop();
            button1.Text = "Start";
            settingslocker(false);
            if (backgroundWorker1.IsBusy)
            {
                backgroundWorker1.CancelAsync();
            }
        }
    }

    private void settingslocker(bool indi)
    {
        if(indi)
        {
            textBox1.Enabled = false;
            textBox3.Enabled = false;
        }
        else
        {
            textBox1.Enabled = true;
            textBox3.Enabled = true;
        }
    }

    private bool connectionchecker()
    {
        try
        {
            con.Open();
            con.Close();
            return true;
        } catch
        {
            return false;
        }
    }

My question is how do I reduce CPU usage running multiple same application I build?

Upvotes: 0

Views: 758

Answers (1)

user585968
user585968

Reputation:


TL; DR: your code is inefficiently handling TCP I/O by spamming new reader threads. This can lead to high RAM usage, page faults and ultimately high CPU-use due to Windows memory compression


Re update, I can see now that your BackgroundWorker is spamming a new thread to INCOMINGTHREAD() whenever data is ready to be read on the SimpleTcpServer.

Apart from being highly inefficient, depending on exactly how long INCOMINGTHREAD() takes to complete and for the thread to be released, you could exhaust the available threads for your process (and perhaps Windows entirely?) very quickly.

Excessive threads and RAM

Each Windows thread consumes 1 MB of RAM and so creating excessive threads has a follow-on effect of consuming excessive RAM. The OS will try to satisfy your request by requesting memory as well as a logical thread. As the demand for threads increases and depending on your system and version of Windows, as you approach the RAM limit certain versions of Windows 10 will start to compress memory in order to save space. Now we're in for real trouble as in order to reduce memory pressure, Windows will compress memory and this has an impact on the CPU!

I've seen quite a few business laptops with say 16 GB RAM being used for development to max out on both RAM and CPU rather quickly with the former having a direct impact on the latter.

Alternatives

Instead of using BackgroundWorker and new Thread() you should look into using asynchonous I/O via async/await and the equivalent async members of SimpleTcpServer (if any).

Alternatively use the older TcpListener as it supports asynchronous operation. This class may not have built-in Task-awareness but you can easily create a Task-based Asynchronous Pattern (TAP) for it.

In doing this you vastly reduce the amount of threads your app needs, the CPU time involved, memory requirements and reduction in possible Windows 10 memory compression activity.

Upvotes: 1

Related Questions