从另一个线程访问“RichTextBox”组件

问题描述 投票:0回答:4

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

但是,我不想在主线程中从我的主类访问

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
组件(我想更改组件的一些变量)而不发生此错误?

c# multithreading winforms console-application
4个回答
3
投票

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

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

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

我还建议您阅读一下this,因为我看到人们建议在控件上的 Winforms 应用程序中使用 Invoke 与 BeginInvoke

简短总结:

对于 Windows 窗体应用程序,我建议您通常应该使用 开始调用。这样你就不用担心死锁了


0
投票

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

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

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

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

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


0
投票

简单的调用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


-2
投票

尝试设置以下属性。

RichTextBox.CheckForIllegalCrossThreadCalls=false;

这可能对你有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.