15.3.10 窗体下使用多线程

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

从.Net FrameWork2.0开始,为了加强了程序安全,防止跨线程调用导致不可预知的结果。微软将窗体主线程(UI控件线程)和其它线程分开,不允许从其它线程直接跨线程访问窗体主线程。在控制台下面使用多线程不用考虑操作界面的问题,但是在窗体界面下使用多线程,会因为访问控件方法或属性的线程不是创建该控件的线程,在编译调试时产生错误。

先看以下例子:

【例 15.23【项目:code15-023】求1至10亿所有整数之和。

代码和【例 15.6】基本相同,但这次将求得的和显示在文本框中。

增加一个TextBox控件,将【例 15.6】的代码:

     MessageBox.Show(sum.ToString());

修改为:

     TextBox1.Text = sum.ToString();

运行代码会抛出一个“InvalidOperationException”异常:线程间操作无效:从不是创建控件"TextBox1"的线程访问它。

图15-21 跨线程访问异常

注意:直接运行编译后的exe程序,并不会产生错误。

5.3.10.1 CheckForIllegalCrossThreadCalls

CheckForIllegalCrossThreadCalls是Control类的一个属性,通过设置true或者false来指示程序是否捕获对错误线程的调用。如果需要跨线程设置UI,只需要让程序不捕获是否跨线程,将CheckForIllegalCrossThreadCalls设置为false即可。

【例 15.24【项目:code15-024】使用CheckForIllegalCrossThreadCalls跨线程设置UI。

        private void Form1_Load(object sender, EventArgs e)

        {

            //窗体的所有控件都不检查是否跨线程调用

            CheckForIllegalCrossThreadCalls = false;

            //以下代码TextBox不检查是否跨线程调用

            //TextBox.CheckForIllegalCrossThreadCalls = false;

        }

        private void Button1_Click(object sender, EventArgs e)

        {

            //将求和的方法地址传递给Thread的构造函数

            Thread th = new Thread(getSum);

            //启动线程

            th.Start();

        }

        //这里是求1-10亿所有整数的和

        private void getSum()

        {

            Int64 sum = 0;

            for (Int64 i = 1; i <= 1000000000; i++)

                sum += i;

            TextBox1.Text = sum.ToString();

        }

运行结果如下图所示:

图15-22 正常输出计算结果

注意:这种方法只是简单地禁止了检查跨线程错误,是非线程安全的,可能会引发不可预料的线程错误,一般不建议使用。

15.3.10.2 使用委托和Invoke

窗体控件提供Invoke 方法,可以在拥有此控件的基础窗口句柄的线程上执行指定的委托,而在委托中完成UI控件修改。

Invoke方法其中一个重载:

public object Invoke (Delegate method, params object[] args);

参数说明:

  1. method:一个方法委托,它采用的参数的数量和类型与args参数中所包含的相同。
  2. args:作为指定方法的参数传递的对象数组。如果此方法没有参数,args可以设置为null。

注意:Invoke方法另外一个不带args参数的版本接受不带参数的委托。

使用委托和Invoke方法跨线程操作UI界面的基本步骤:

1、创建一个调用方法A,采用多线程调用方法C;

2、声明一个类级的委托B,其参数和调用方法C相同;

3、创建新线程要调用的方法C,在这个方法里面创建需要委托的方法实例D,并关联了E;

4、创建委托关联的方法E,在这个方法中修改UI;

5、在方法C中使用需要修改的控件UI的Invoke方法F。

另外,在方法C中可以先采用InvokeRequired属性判断是否必须调用Invoke方法。

【例 15.25【项目:code15-025】使用委托和Invoke跨线程设置UI

        //委托B:声明一个委托,参数与要调用的方法相同

        private delegate void showSum(Int64 sum);

        //方法A

        private void button1_Click(object sender, EventArgs e)

        {

            Thread th = new Thread(getSum);

            th.Start();

        }

        //方法C:这里是求1-10亿所有整数的和

        private void getSum()

        {

            Int64 sum = 0;

            for (Int64 i = 1; i <= 1000000000; i++)

                sum += i;

            if (textBox1.InvokeRequired)

            {

                //D:获得委托的实例

                showSum newsum = new showSum(showsumIntext);

                //F:控件的Invoke方法调用方法并传递参数

                textBox1.Invoke(newsum, sum);

            }

            else

                textBox1.Text = sum.ToString();

        }

        //E:委托关联的方法,在这个方法中修改UI

        private void showsumIntext(Int64 sum)

        {

            textBox1.Text = sum.ToString();

        }

运行结果同【例 15.24】。

15.3.10.3 使用MethodInvoker 委托

MethodInvoker委托可执行托管代码中声明为 void 且不接受任何参数的任何方法,在调用控件的Invoke方法或需要一个简单委托又不想自己定义时可以使用该委托。

【例 15.26【项目:code15-026】使用MethodInvoker和Invoke跨线程设置UI

        Int64 allsum;

        private void button1_Click(object sender, EventArgs e)

        {

            Thread th = new Thread(getSum);

            th.Start();

        }

        private void getSum()

        {

            Int64 sum = 0;

            for (Int64 i = 1; i <= 1000000000; i++)

                sum += i;

            allsum = sum;

            MethodInvoker showSum = showsumIntext;

            textBox1.Invoke(showSum);

        }

        //无参数,无返回值的方法

        private void showsumIntext()

        {

            textBox1.Text = allsum.ToString();

        }

运行结果同【例 15.24】。

学习更多vb.net知识,请参看vb.net 教程 目录

学习更多C#知识,请参看C#教程 目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/19564.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core SixLabors.ImageSharp v3.x 的图像实用程序类

使用用 C# 编写的 asp.net core web 应用程序示例在 Windows 和 Linux web 服务器上处理图像&#xff0c;包括创建散点图和直方图&#xff0c;以及根据需要旋转图像以便正确显示。 这个小型实用程序库需要将 NuGet SixLabors.ImageSharp包&#xff08;版本 3.1.x&#xff09;添…

【leetcode】200.岛屿数量(DFS入门)

实战总结 用char型接收整形int转化为的对应字符要小心 int res; char res 0; 其中 res 的上限是127。 在下面这道题中&#xff0c;笔者一开始想将遍历过的位置更新值为 res ‘0’&#xff0c;但当岛屿数过多的时候就溢出了&#xff0c;所以还是应该将遍历过的位置更新为‘…

CES Asia 2025“科技+文旅”融合计划:开启文旅新篇

CES Asia 2025第七届亚洲消费电子技术贸易展&#xff08;赛逸展&#xff09;将在首都北京盛大举行&#xff0c;其亮点十三“‘科技文旅’融合计划”备受瞩目&#xff0c;为科技与文旅产业的深度融合带来了新的契机与活力。 在“科技文旅”融合计划中&#xff0c;景区智能设备租…

【Git版本控制器】第三弹——版本回退,撤销修改,删除文件

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 相关笔记&#xff1a; https://blog.csdn.net/djd…

DeepSeek ,银行营销会被 AIGC 颠覆吗?

AI 让银行营销更智能&#xff0c;但更重要的是“懂客户” AI 在银行营销中的应用已经不仅仅局限于文案生成&#xff0c;而是渗透到了整个营销流程。 据悉&#xff0c;中国银行已经开始利用 AI 大模型构建智能营销助手系统&#xff0c;结合知识图谱和 AI 技术&#xff0c;实现…

【产品推介】可驱动5A负载的降压型DC/DC转换器XBL1663

一、产品简介 采用ESOP-8封装的XBL1663最大可输出5A电流 芯伯乐XBL1663是一款专为降压型DC/DC转换器设计的单片集成电路&#xff0c;具有高转换效率、恒定开关频率工作的特点。内置功率 MOSFET可在 4.5 V-40V 输入电源上实现 5A 峰值输出电流&#xff0c;并具有出色的负载和线…

Rust编程语言入门教程(四)猜数游戏:一次猜测

目录 引言猜数游戏——目标一、创建项目二、编写代码三、运行代码四、代码解释总结 引言 猜数游戏是一个经典的编程练习&#xff0c;它不仅能够帮助开发者熟悉基本的输入输出操作&#xff0c;还能深入理解条件判断和用户交互的逻辑。在 Rust 中&#xff0c;通过标准库提供的 s…

.NET版PDF处理控件Aspose.PDF教程:在 C# 中将 TIFF 文件转换为 PDF

将TIFF文件转换为PDF文档在各个行业中都是必不可少的。许多企业需要将文档转换为存档、共享或打印。TIFF 文件通常用于图像&#xff0c;而 PDF 是文档共享的标准。将 TIFF 文件转换为 PDF 可确保跨不同平台的兼容性和易用性。在这篇博文中&#xff0c;我们将探讨如何使用 Aspos…

DeepSeek视角下学术论文创新点探索干货分享!

学术论文的创新性是推动知识进步和科学发展的关键因素。它不仅是学术研究的基本要求&#xff0c;也是研究者专业能力的重要体现。本文将探讨学术论文创新的重要性&#xff0c;并分析DeepSeek在促进学术论文创新方面可能发挥的独特作用。 1.创新为啥这么重要&#xff1f; 1. 探…

EasyRTC智能硬件:实时畅联、沉浸互动、消音护航

在当今智能硬件迅猛发展的时代&#xff0c;音视频通讯技术已成为设备与用户、设备与设备间不可或缺的沟通纽带。而EasyRTC&#xff0c;凭借其无可比拟的实时性能、卓越的互动感受以及强大的交互实力&#xff0c;正逐步演变为智能硬件领域的“超级动力”核心。特别是其倾力打造的…

matlab汽车动力学半车垂向振动模型

1、内容简介 matlab141-半车垂向振动模型 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

重生之我在异世界学编程之C语言:深入预处理篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、预处理的作用与流程&#xf…

观察者模式说明(C语言版本)

观察者模式主要是为了实现一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时&#xff0c;会通知所有观察者对象&#xff0c;使它们能够自动更新自己。下面使用C语言实现了一个具体的应用示例&#xff0c;有需要的可以参考…

Zotero PDF Translate插件配置百度翻译api

Zotero PDF Translate插件可以使用几种翻译api&#xff0c;虽然谷歌最好用&#xff0c;但是由于众所周知的原因&#xff0c;不稳定。而cnki有字数限制&#xff0c;有道有时也不行。其他的翻译需要申请密钥。本文以百度为例&#xff0c;进行申请 官方有申请教程&#xff1a; Zot…

无人机遥感:如何助力智慧农业中的农林信息提取?

目录 综合态势分析农作物形态信息提取理论与实践农作物生理生化信息提取理论与实践农作物胁迫信息提取理论与实践农作物产量信息提取理论与实践遥感提取结果的空间表达——GIS制图流程 前言 无人机遥感技术在农林信息提取中的应用已成为智慧农业和生态监测的重要手段。通过搭载…

【线段树 二分查找】P3939 数颜色|普及+

本文涉及知识点 C线段树 C二分查找 P3939 数颜色 题目背景 大样例可在页面底部「附件」中下载。 题目描述 小 C 的兔子不是雪白的&#xff0c;而是五彩缤纷的。每只兔子都有一种颜色&#xff0c;不同的兔子可能有 相同的颜色。小 C 把她标号从 1 到 n n n 的 n n n 只兔…

网络工程师 (44)ARP协议

前言 ARP协议&#xff0c;即地址解析协议&#xff08;Address Resolution Protocol&#xff09;&#xff0c;是一种网络协议&#xff0c;主要用于将网络层的IPv4地址&#xff08;逻辑地址&#xff09;解析为链路层的物理地址&#xff08;通常是MAC地址&#xff09;。 一、基本概…

深入解析 vLLM:高性能 LLM 服务框架的架构之美(一)原理与解析

修改内容时间2.4.1处理请求的流程&#xff0c;引用更好的流程图2025.02.11首发2025.02.08 深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;一&#xff09;原理与解析 深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;二&#xff09;…

Web安全|渗透测试|网络安全

基础入门(P1-P5) p1概念名词 1.1域名 什么是域名&#xff1f; 域名&#xff1a;是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称&#xff0c;用于在数据传输时对计算机的定位标识&#xff08;有时也指地理位置&#xff09;。 什么是二级域名多级域名&am…

JavaSE的基础语法(5)

一.Java中的方法 函数:把完成某一特定功能的代码进行抽取,把他们卸写在一组大括号中,为其命名通过函数名调用即可 Java中的方法:类似于其他语言中的函数(在面向对象的语言中习惯称之为方法,且不能独立存在,需要定义在类中) 将完成某个特定功能的某一段代码封装到一个有名称的代…