【问题标题】:Access "RichTextBox" Component from another thread从另一个线程访问“RichTextBox”组件
【发布时间】:2017-04-04 18:29:26
【问题描述】:

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

但是,我不想在主线程中从我的主类访问 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 组件(我想更改组件的一些变量)而不发生此错误?

【问题讨论】:

  • 附带说明,Application.Run() 是一个阻塞调用。在聊天表单关闭之前,您的while (RemoteChat) 循环将不会被点击!
  • @Idle_Mind 哦,你是对的!谢谢!

标签: c# multithreading winforms console-application


【解决方案1】:

控件归创建它的线程所有。 在您的情况下,您启动的线程拥有表单,因为它会绘制表单,因此它将成为您的表单 ui 线程。

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

richTextBox1.BeginInvoke(new Action(()=>
{
// make changes to control here.
}));

【讨论】:

    【解决方案2】:

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

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

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

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

    “CheckForIllegalCrossThreadCalls = false”是一个解决方案,如果在复杂的程序中使用它有足够的危险。 希望对您有所帮助。

    【讨论】:

      【解决方案3】:

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

      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

      【讨论】:

        【解决方案4】:

        尝试设置以下属性。

        RichTextBox.CheckForIllegalCrossThreadCalls=false;
        

        这可能会对你有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多