前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#报错——(Winform) 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

C#报错——(Winform) 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

作者头像
vv彭
发布2021-03-07 10:54:17
3K0
发布2021-03-07 10:54:17
举报
文章被收录于专栏:c#学习笔记c#学习笔记

问题点描述:

  我新建一个线程,并在这个线程中,把某个控件的父级去掉或者更改,导致报这个异常

网上的解析如下:

  “Windows 窗体”使用单线程单元 (STA) 模型,因为“Windows 窗体”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。有关 .NET Framework 中的线程的信息,请参见线程处理

STA 模型要求需从控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。基类 Control 为此目的提供了若干方法(Invoke、BeginInvoke 和 EndInvoke)。Invoke 生成同步方法调用;BeginInvoke 生成异步方法调用。

如果您在控件中为大量占用资源的任务使用多线程,则用户界面可以在背景线程上执行一个大量占用资源的计算的同时保持可响应。

用人话描述为:控件是属于主线程(UI线程),不可以跨线程修改其父级。

网上找到的答案是:

代码语言:javascript
复制
 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
       //创建线程并调用方法CreateUI
            Thread t = new Thread(new ThreadStart(CreateUI));
            t.Start();
        }
     

     //
        private void CreateUI()
        {
            AddTextBox();
        }
 
        private void AddTextBox()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate { AddTextBox(); }));
                return;
            }
            TextBox tb = new TextBox();
            tb.Text = "test";
            this.Controls.Add(tb);
        }
 
    }

看起来感觉很绕,而且很麻烦,又要新建方法,又要新建委托

所以我把它简化如下:

代码语言:javascript
复制
           //使用拉姆达表达式创建一个委托,委托里面修改控件的父级
          Action delega1 = () =>
                {
                    tabPageIO.Parent = null;
                    tabPageIO.Parent = tabControlWav;
                };

                //使用异步多线程更新
                if (this.InvokeRequired)
                {
            //新建一个线程,线程里面调用拉姆达表达式,拉姆达表达式里面使用异步的形式调用委托,委托里面再修改控件的父级
                    new Thread(() => this.Invoke(delega1)).Start();
                }
                else
                {
                    delega1();
                }

拉姆达表达式真的是好东西,看起来很简洁

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-02-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档