0

Below is a function I have running in a while(true) loop in a thread running a Winforms GUI. I have a button set to put text data into the inBuffer object. this always works, however when I place into the buffer object from a different thread, the data is detected, pulled, and printed out in the Console.out.WriteLine statement, however it never shows up in the Display (textBox) object

public void put()
    {   
        string strDisplayMe = ModemKind.MainClass.inBuffer.MkRequest();
        if (strDisplayMe != "")
        {
            Console.Out.WriteLine("FOUND SOMETHING IN BUFFER: " + strDisplayMe);
            char[] DisplayMeArr = strDisplayMe.ToCharArray ();
            for (int i = 0; i <= DisplayMeArr.Length -1; ++i) 
            {
                this.display.Text += DisplayMeArr [i];
                Thread.Sleep (100);
            }
        this.display.Text += '\n';
        }
    }

EDIT: this is a separate class from what is feeding it data through the static buffer objects

  • Look at `Invoke()`, i.e. `this.display.Invoke((MethodInvoker) delegate {this.display.Text += DisplayMeArr [i];});` – Dmitry Bychenko Jan 29 '15 at 07:23
  • Did you get a chance to look at the following question? [link](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c?rq=1) – sundar Jan 29 '15 at 07:24

2 Answers2

0

Only the main window thread can access/change controls... if you want update the UI from the thread that runs the loop, you need to sync the call with the main thread using the Control.Invoke method.

For instance...

public void put()
{   
    string strDisplayMe = ModemKind.MainClass.inBuffer.MkRequest();
    if (strDisplayMe != string.Empty)
    {
        char[] DisplayMeArr = strDisplayMe.ToCharArray();
        for (int i = 0; i <= DisplayMeArr.Length -1; ++i) 
        {
            this.UpdateUI(() => { this.display.Text += DisplayMeArr[i]; });
            Thread.Sleep(100);
        }

        this.UpdateUI(() => { this.display.Text += '\n'; });
    }
}

private void UpdateUI(Action handler)
{
    this.Invoke(handler);
}
Matze
  • 5,100
  • 6
  • 46
  • 69
0

You can use MethodInvoker to access TextBox from other thread then GUI thread. Make a method to access the TextBox using MethodInvoker. you are assigning text multiple times consider assigning it once for performance, and use StringBuilder for string concatenation.

public void put()
{   
    string strDisplayMe = ModemKind.MainClass.inBuffer.MkRequest();
    if (strDisplayMe != "")
    {
        Console.Out.WriteLine("FOUND SOMETHING IN BUFFER: " + strDisplayMe);
        char[] DisplayMeArr = strDisplayMe.ToCharArray ();
        for (int i = 0; i <= DisplayMeArr.Length -1; ++i) 
        {
            AssignToTextBox(this.display, this.display.Text + DisplayMeArr [i]);
            Thread.Sleep (100);
        }
    AssignToTextBox(this.display, this.display.Text +  '\n');
    }
}

void AssignToTextBox(TextBox txtBox, string value)
{
  if(txtBox.InvokeRequired)
  {
      txtBox.Invoke(new MethodInvoker(delegate { txtBox.text = value;      }));
  }
}

Edit You can use BeginInvoke instead of Invoke to call it asynchronously. Read more about the Invoke and BeginInvoke in this question.

void AssignToTextBox(TextBox txtBox, string value)
{
      txtBox.BeginInvoke(new Action(()=>txtBox.Text = value ));
}
Community
  • 1
  • 1
Adil
  • 146,340
  • 25
  • 209
  • 204