Search code examples
c#multithreadingtextbox

c# Texbox constantly showing "old" data when its text is changed from another thread


App description: My application shows list of a running processes and when you click on process it should show some data on textboxes.

Problem: Im trying to update textbox from another thread by using delegate function.When I run my app and choose first process,everything shows up correctly in textboxes,but when i choose second process,third and so on,textboxes start to show "old" data too(data from previously clicked processes).

It acts like i stored data from every clicked process in some array or stack and then shows it all in textboxes really fast.For example:If i click on process chrome.exe that is using 50 mb of ram,my textbox will show "50 mb",and if i click on process calculator.exe that is using 5 mb after that,my texbox will show "50 mb" and few seconds after "5mb",and it will keep repeating that all the time.

Code that executed on click:

 private void Lista_procesa_prikaz_MouseClick(object sender, MouseEventArgs e)       
    {
        refresh = true;
        RamTextBox.Text = CpuTextBox.Text = Description_textbox.Text = "";
        var proc = System.Diagnostics.Process.GetProcessById(Int32.Parse(Lista_procesa_prikaz.Items[Lista_procesa_prikaz.FocusedItem.Index].SubItems[1].Text));
        ThreadRefresh = new Thread(() => ProcesKlik(proc));
        ThreadRefresh.IsBackground = true;
        ThreadRefresh.Start();
     }

ProcesKlik Thread:

        private void ProcesKlik(Process proc)
    {
        do
        {
            try
            {
                PerformanceCounter CpuCounter = new PerformanceCounter("Process", "% Processor Time", proc.ProcessName);
                CpuCounter.NextValue();
                Thread.Sleep(2000);
                float postotak = (float)CpuCounter.NextValue() / cpucount;        
                TextBoxChange(CpuTextBox, "Processor usage:" + postotak.ToString("n1") + "%");
                bytesTo Mb = new bytesTo(proc.WorkingSet64);
                TextBoxChange(RamTextBox,"Ram usage:" +  Mb.ToMb().ToString() + "Mb");
            }
            catch(InvalidOperationException)
            {
                refresh = false;
                MessageBox.Show("Process is terminated.");
            }
        }
        while (refresh);
    }

TextBoxChange delegate function for changing textbox content from another thread:

    delegate void TextBoxChangeCallback(TextBox textbox, string text);
    private void TextBoxChange (TextBox textbox,string text)
    {
        if (textbox.InvokeRequired)
        {
            TextBoxChangeCallback deg = new TextBoxChangeCallback(TextBoxChange);
            this.Invoke(deg, new object[] { textbox, text });
        }
        else
            textbox.Text = text;
    }

Solution

  • Problem was, like Sam Axe suggested in comment, that i never stopped running threads, so that "showing old data" actually were threads that were still running and writing data to textboxes. I solved my problem by using flags(boolean variables) for stopping thread before starting a new one.