C#winforms GUI不接受来自其他线程的数据

时间:2015-01-29 07:19:48

标签: c# multithreading winforms

下面是我在运行Winforms GUI的线程中运行while(true)循环的函数。 我有一个按钮设置将文本数据放入inBuffer对象。这总是有效,但是当我从另一个线程放入缓冲区对象时,数据在Console.out.WriteLine语句中被检测,拉出和打印出来,但是它永远不会出现在Display(textBox)对象中

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';
        }
    }

编辑:这是一个单独的类,它通过静态缓冲区对象提供数据

2 个答案:

答案 0 :(得分:0)

只有主窗口线程可以访问/更改控件...如果要从运行循环的线程更新UI,则需要使用Control.Invoke方法将调用与主线程同步。 / p>

例如......

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);
}

答案 1 :(得分:0)

您可以使用MethodInvoker从其他线程然后GUI线程访问TextBox。制作一种方法,使用MethodInvoker访问TextBox。您要多次分配文本,请考虑为性能分配一次,并使用StringBuilder进行字符串连接。

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;      }));
  }
}

编辑您可以使用BeginInvoke代替Invoke来异步调用它。详细了解此question中的InvokeBeginInvoke

void AssignToTextBox(TextBox txtBox, string value)
{
      txtBox.BeginInvoke(new Action(()=>txtBox.Text = value ));
}