在不同线程上创建的C#控件无法作为父控件与其他线程上的控件关联。

8
我正在运行一个线程,该线程获取信息并创建标签来显示它。这是我的代码:
    private void RUN()
    {
        Label l = new Label();
        l.Location = new Point(12, 10);
        l.Text = "Some Text";
        this.Controls.Add(l);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(new ThreadStart(RUN));
        t.Start();
    }

有趣的是我之前写过一个应用程序,它有一个面板,我曾经使用线程添加控件而没有遇到任何问题。但是这个应用程序不允许我这样做。

1
你只能在 UI 线程中修改 UI 元素。 - Leri
1
将业务逻辑(信息获取)与用户界面(创建标签)分开。 - H H
1
为什么要创建线程来添加UI元素? - Parimal Raj
可能是重复的问题:在非 UI 线程中创建控件 - H H
3个回答

12

你无法从另一个线程更新UI线程:

 private void RUN()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke((MethodInvoker)delegate()
                {
                    Label l = new Label(); l.Location = new Point(12, 10);
                    l.Text = "Some Text";
                    this.Controls.Add(l);
                });
            }
            else
            {
                Label l = new Label();
                l.Location = new Point(12, 10);
                l.Text = "Some Text";
                this.Controls.Add(l);
            }
        }

6

您需要使用BeginInvoke从另一个线程安全地访问UI线程:

    Label l = new Label();
    l.Location = new Point(12, 10);
    l.Text = "Some Text";
    this.BeginInvoke((Action)(() =>
    {
        //perform on the UI thread
        this.Controls.Add(l);
    }));

无法使用 错误1:使用泛型类型“System.Action<T>”需要一个类型参数。 - BOSS

3

您正在尝试从不同的线程向父控件添加控件,但只能在创建父控件的线程中将控件添加到父控件中!

使用Invoke方法可以安全地从另一个线程访问UI线程:

    Label l = new Label();
    l.Location = new Point(12, 10);
    l.Text = "Some Text";
    this.Invoke((MethodInvoker)delegate
    {
        //perform on the UI thread
        this.Controls.Add(l);
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接