C#线程间操作无效:从不是创建控件“textbox1”的线程访问它

这篇具有很好参考价值的文章主要介绍了C#线程间操作无效:从不是创建控件“textbox1”的线程访问它。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  在C#的多线程访问中,在线程间的相互访问时因为线程安全问题有访问限制,在创建一般线程时,对于界面元素访问时这样的问题比较常见。

  比如,创建一个form1,上面放置一个textbox控件,创建一个线程去访问textbox,界面如下:

C#线程间操作无效:从不是创建控件“textbox1”的线程访问它

  按钮buuton1的代码:

        private void button1_Click(object sender, EventArgs e)
        {
            var thread1 = new System.Threading.Thread(Func1);
            thread1.Start();
        }

  就是简单地创建一个线程,线程里面运行的func1代码:

        private void Func1()
        {
            for(int i = 0; i < 5; i++)
            {
                textBox1.Text = textBox1.Text+ $"线程{Thread.CurrentThread.ManagedThreadId}执行{i}."+Environment.NewLine;
            }
        }

  运行,点击button1按钮系统会报错:

C#线程间操作无效:从不是创建控件“textbox1”的线程访问它

  意思是说:线程间操作无效:从不是创建控件“textbox1”的线程访问它,这是不允许的。

  线程存在安全保护机制,并不能随意访问,因为这样存在冲突的可能。

  解决这个问题,最直接的方法是在界面初始化后去掉控件的跨线程非法访问属性,即将Control.CheckForIllegalCrossThreadCalls属性设置为false即可。

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

  这样结果就出来了。

  一般情况下,还是不要设置Control.CheckForIllegalCrossThreadCalls的属性,那么怎样可以达到修改textbox1的值呢?

  可以通过委托来解决。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var thread1 = new System.Threading.Thread(Func1);
            thread1.Start();
        }

        public void SetText(string SText)
        {
            textBox1.Text = textBox1.Text + SText + Environment.NewLine;
        }

        private void Func1()
        {
            string Str = "";
            for (int i = 0; i < 5; i++)
            {
                Str= $"线程{Thread.CurrentThread.ManagedThreadId}执行{i}."+Environment.NewLine;
                if (textBox1.InvokeRequired)
                {
                    Action SetText111 = delegate { SetText(Str); };
                    textBox1.Invoke(SetText111);
                }
                else
                {
                    textBox1.Text = Str;
                }
            }
        }
    }

  这样也可以达到目的,或者直接写更简单:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var thread1 = new System.Threading.Thread(Func2);
            thread1.Start();
        }

        private void Func2()
        {
            textBox1.Invoke(() =>
            {
                for (int i = 0; i < 5; i++)
                {
                    textBox1.Text = textBox1.Text+ $"线程{Thread.CurrentThread.ManagedThreadId}执行{i}." + Environment.NewLine;
                }
            });
        }

    }

  效果也是一样的。

  在C#中,需要注意Invoke和begininvoke的区别。

  control.invoke(参数delegate):在拥有此控件的基础窗口句柄的线程上执行指定的委托,注意是同步。
  control.begininvoke(参数delegate):在创建控件的基础句柄所在线程上异步执行指定委托,注意这里执行的是异步。

  在跨线程请求时,常检验textBox1.InvokeRequired属性,即是否跨线程请求。文章来源地址https://www.toymoban.com/news/detail-407130.html

到了这里,关于C#线程间操作无效:从不是创建控件“textbox1”的线程访问它的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#线程操作UI控件

    在写winform程序时候,如果时间长的操作不用线程操作。那么会卡死UI,点击界面就体现为未响应。为此需要对耗时操作用线程处理,比如检验的监听程序就是一个死循环,不停检查文件夹或数据库又没有数据,然后上传。如果不时有线程,在数据多的情况,程序是基本点不动

    2024年02月13日
    浏览(26)
  • C# 跨线程访问窗体控件

    在不加任何修饰的情况下,C# 默认不允许跨线程访问控件,实际在项目开发过程中,经常使用跨线程操作控件属性,需要设置相关属性才能正确使用,两种方法设置如下: 方法1:告诉编译器取消跨线程访问检查,在窗体构造函数中编写,如下图所示: 方法2:设置所需的控件

    2024年02月11日
    浏览(33)
  • c# 跨线程访问UI控件

            在一个应用程序中,往往存在两种线程:UI线程和工作线程。         UI线程有窗口,创建窗口的控件,且有消息队列对窗口和控件的消息进行管理。主要处理和UI相关的逻辑。         工作线程主要处理和业务相关的比较复杂的逻辑,当处理好之后有可能会调用U

    2024年02月08日
    浏览(30)
  • C# WinForm 跨线程访问控件

    在WinForm开发中,经常会碰到主线程代码运行过程中需要刷新窗体控件的情况,如果直接在其他线程中去操作窗体控件,这时会抛出线程间操作无效的异常信息,因为窗体控件是由主线程创建的,C#强制要求代码必须是线程安全的,所以不允许跨线程访问。需要使用控件的Inv

    2024年02月04日
    浏览(30)
  • WPF开发经验-WPF的TextBox控件的MouseDown事件不响应的解决方法

    最近项目有个需求,大概是,当点击某个TextBox时,先执行一些业务上的逻辑处理。 于是按以往思维,将TextBox的MouseDown事件关联事件处理方法,将业务处理写在方法里。 调试发现,点击TextBox时,事件处理方法未执行。 通过查阅微软官方文档了解到问题原因。 附上文档链接:

    2024年02月08日
    浏览(33)
  • C#简单向:textbox添加提示内容

    首先: 1.到所要操作的文件(/xx.cs/xx.Designer.cs),这里我是到Form3.cs/Form3.Designer.cs文件 2.找到你所要操作的textBox,楼主是叫textBox1的textBox,如果你们没有修改名字的话,应该也是什么textBox后面加数学什么的。 3.在该textBox下添加 4.到Form3.cs,创建这两个方法 注意点:这两个方法与

    2024年02月09日
    浏览(25)
  • C# textBox 右键菜单 contextMenuStrip

    需求: 想在上图空白处可以右键弹出菜单,该怎么做呢? 1.首先,拖出一个 ContextMenuStrip。  随便放哪里都行,如下:  2.在textBox里关联这个“右键控件”即可,如下:  最终效果如下: 以上 参考:C# 右键菜单 contextMenuStrip_camellias_的博客-CSDN博客 3.添加响应代码: 如图,双击

    2024年02月11日
    浏览(27)
  • c#入门-Task创建线程

    在c#中,有线程类。激活线程对象就可以实现多线程。 不过,这是在代码角度来说的。你可以在代码中创建一万个线程。 但实际上你的cpu没有一万个逻辑处理器来真正同时执行这一万个线程。 所以我们称创建一万个线程为创建一万个并发——我们希望同时执行一万个线程,

    2024年02月01日
    浏览(32)
  • C#调用SqlSugar操作达梦数据库报错“无效的表或视图名”

      安装达梦数据库后,使用SqlSugar连接测试数据库并基于DBFirst方式创建数据库表对应的类,主要代码如下:   运行到CreateClassFile函数时报如下错误:   通过达梦管理工具查看数据库,PERSON数据库下有ADDRESS表,不清楚为什么报错。   百度错误信息,检索结果中介绍可

    2024年01月25日
    浏览(39)
  • 【WinForm详细教程一】WinForm中的窗体、Label、TextBox及Button控件、RadioButton和CheckBox、ListBox

    .sln文件 :解决方案文件 位置引用 bin文件夹 : 存放项目的编译结果 exe dll debug 调试 release 发布 pdb 位置信息–调试 obj文件夹 object 编译过程中生成的中间临时文件 加快编译速度 Properties 引用 添加引用 --选择需要的程序集 App.config 配置文件 .csproj 项目文件 位置引用 双击打开

    2024年02月08日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包