访问" RichTextBox"来自另一个线程的组件

时间:2017-04-04 18:29:27

标签: c# multithreading winforms console-application

我有一个控制台应用程序,它在另一个线程中启动一个表单应用程序(来自另一个类)。

但是,我不想在主线程中从我的主类访问richTextBox1组件,并且会抛出一个错误,说我试图从另一个组件访问该组件线程。

我的代码: (表格申请)

public partial class ChatGui : Form
{
    public static RichTextBox textBox;
    public ChatGui()
    {
        InitializeComponent();
        richTextBox1.ReadOnly = true;
        richTextBox1.BackColor = SystemColors.Window;
    }

    public void WriteLine(string line)
    {
        richTextBox1.Text += line+"\r\n";
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            WriteLine("[You]: "+textBox1.Text);
            NetworkManager.SendPacket("rchat_msg " + textBox1.Text.Replace(" ", "%20"));
            textBox1.Text = "";
            e.Handled = true;
        }
    }

    public void Exit()
    {
        Application.Exit();
    }

    private void ChatGui_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
    }

}

主控台应用程序

public static void StartRemoteChat()
    {
        RemoteChat = true;
        Program.ChatGui = new ChatGui();
        new Thread(new ThreadStart(() =>
        {
            Application.Run(Program.ChatGui);
            while (RemoteChat)
            {
                // ...
            }
        })).Start();
    }

那么,如何在不发生此错误的情况下从主线程中访问richTextBox1组件(我想更改组件的某些变量)?

4 个答案:

答案 0 :(得分:3)

该控件由创建它的线程拥有。 在你的情况下,你开始的线程拥有表单,因为它绘制它,因此它将成为你的表单ui线程。

但是,当您尝试使用另一个线程对控件进行更改时,它将像您所说的那样抛出异常。 解决这个问题的方法是调用创建它的线程来进行所需的更改:

var reverseObj = function(object) {
    var NewObj = {}, keysArr = Object.keys(object);
    for (var i = keysArr.length-1; i >= 0; i--) {
        NewObj[keysArr[i]] = object[keysArr[i]];
    }
    return NewObj;
}

答案 1 :(得分:0)

可以帮助你的是“CheckForIllegalCrossThreadCalls = false;”但在这里使用(开头):

public Form1()
    {
        InitializeComponent();
        CheckForIllegalCrossThreadCalls = false;            
    }

建议是使用每次调用“RichTextBox1”的invoke方法。 此方法允许与其他线程创建的元素进行交互。 例如:

richTextBox1.Invoke(new Action(() => richTextBox1.Text = "hello word"));

“CheckForIllegalCrossThreadCalls = false”是一种在复杂程序中使用时具有足够危险的解决方案。 我希望我能提供帮助。

答案 2 :(得分:0)

简单的调用调用从新线程调用该方法:

if (InvokeRequired)
{
     Invoke(new Action(**METHODHERE**));
     return;
}

并传递参数:

if (InvokeRequired)
{
     Invoke(new Action<string>(**METHODHERE**) **parameter**);
     return;
}

好读:https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx

答案 3 :(得分:-2)

尝试设置以下属性。

RichTextBox.CheckForIllegalCrossThreadCalls=false;

这可能会对你有帮助。